2010-07-14 4 views
0

J'ai créé une application Android et il y a une fonction qui supprime périodiquement les anciens enregistrementsComment optimiser la suppression avec la clause date range where?

delete from tablea where col1 = 'value1' and col2 = 'value2' and postdate < '2010-06-14' 

Il a un problème de performances lorsque le nombre total de ligne dans TableA a plus de 50 000. Il faut environ 45 secondes pour supprimer 500 enregistrements.

J'ai déjà index pour cette clause where:

CREATE INDEX indexa on tablea (col1, col2, postdate) 

ajoutant PRAGMA synchrone = OFF et PRAGMA count_changes = OFF n'a pas aidé.

S'il vous plaît conseiller

+0

Vérifiez quel est le code d'octet généré pour cette requête et s'il utilise les indices annoncés. –

Répondre

0

Il me semble que si l'index n'est pas utile comme écrit. Je pense que vous voudriez:

CREATE INDEX indexa on tablea (col1, col2) 
CREATE INDEX indexb on tablea (postdate) 

comme lu, mon interprétation de la documentation dit que pour comprendre ce que la ligne est appelée dans votre exemple, la base de données doit avoir une date précise pour correspondre à une donnée paire de valeurs (de sorte qu'il peut rechercher l'index/index). Vous n'avez pas de date spécifique. Au lieu de cela, vous recherchez une plage de valeurs de date. Le problème est la comparabilité des valeurs de date est subsumed dans l'index de combinaison que vous avez créé, de sorte que vous ne pouvez pas obtenir cette information très facilement, ce qui rend l'index d'utilisation limitée.

Bien sûr, je pourrais en être plein. Mon expérience principale n'est pas avec sqlite. Pourtant, il ne devrait pas faire beaucoup de mal à essayer ce qui précède.

+0

SQLite utilisera uniquement un index par table dans la clause FROM. Donc diviser l'index en deux n'aidera pas pour cette requête. – Qberticus

+0

Ça ne ferait pas de mal, car l'index ci-dessus ne va pas utile autant que je peux dire naïvement. Au moins les deux index seraient utiles séparément, non? sqlite aurait à choisir ce qu'il aimait mieux. – Slartibartfast

1

Vérifiez le type de votre champ postdate. SELECT typeof(postdate). Il semble que SQLite va le traiter comme TEXT en fonction de votre clause where. SQLite n'a pas de concept de type 'date' seulement une affinité NUMERIC va se produire pour n'importe quelle 'date'. Si vous n'insérez pas NUMERIC s alors il fait probablement des comparaisons de chaînes et cela sera plus lent que les comparaisons d'entiers que vous attendez. Si vous insérez NUMERIC s, alors votre clause where peut être à l'origine d'être castée en TEXT d'abord, puis en appliquant les critères de la clause where. Vous pouvez consulter le documentation about datatypes.

+0

Je pense que vous avez raison. typeof (postdate) = 'texte'. Je vais le modifier tonite et poster le résultat ici. – kentsang77