2012-04-24 3 views
1

J'ai un petit problème; J'ai 2 tables: events et multimedia. events ont leSupprimer la requête sql est très très lent

id, 
device_id 
created_at field 

la clé primaire est l'identifiant et il y a un indice formé par device_id et created_at champ.

multimedia tableau ont le champ suiveur:

id 
device_id 
created_at 
data (this field is a blob field and contains a 20k string) 

la clé primaire est id et il y a un index formé par device_idcreated_by et terrain.

Le problème est lorsque je veux supprimer l'enregistrement avec created_at avant une donnée.

la requête:

DELETE FROM events WHERE device_id = #{dev[0]} 
AND created_at <= '#{mm_critical_time.to_s}' 

est ok. Dans 5 ou 6 secondes delete l'enregistrement.

La requête

DELETE FROM multimedia WHERE device_id = #{dev[0]} 
AND created_at <= '#{mm_critical_time.to_s}' 

me donner un problème, le début d'exécution et de ne jamais terminer.

quel est le problème?

Répondre

2

Vous devez probablement créer un index pour les colonnes que vous recherchez.

CREATE INDEX device_created_index 
ON multimedia (device_id, created_at); 

Si vous voulez en savoir plus sur l'optimisation des requêtes, reportez-vous à la réponse que je donnai ici sur l'utilisation EXPLIQUER SELECT: is there better way to do these mysql queries?

+0

j'ai crée déjà cet index – Dabidi

+0

alors je vous suggère EXPLIQUEZ vos requêtes comme mentionné dans la réponse que je lié. –

0

l'ordre des conditions est important, vous havent't nous a dit votre serveur de base de données, mais au moins dans Oracle il est, alors essayez de les inverser comme

DELETE FROM multimedia WHERE 
created_at <= '#{mm_critical_time.to_s}' 
AND device_id = #{dev[0]} 

nous ou une requête intérieure sur la partie la plus rapide

DELETE FROM multimedia WHERE 
created_at <= '#{mm_critical_time.to_s}' 
AND device_id in (select device_id from multimedia where device_id = #{dev[0]}) 

De plus, je casse toujours les requêtes lentes et je teste les parties sur la vitesse afin que vous sachiez où se trouve le goulot d'étranglement. Certains programmes vous montrent combien de temps une requête a pris et dans Ruby vous pouvez utiliser le benchmark, vous pouvez compléter la suppression avec un select pendant le test.

si test:

select * FROM multimedia WHERE created_at <= '#{mm_critical_time.to_s}' 

et

select * from multimedia WHERE device_id = #{dev[0]} 

succès ..

0

Il est tout à fait naïf de donner des solutions aux problèmes de performance dans les bases de données relationnelles sans connaître toute l'histoire , car il y a beaucoup de variables impliquées.

Pour les données que vous avez fournies si, je vous suggère de déposer les clés primaires et les index et exécutez:

CREATE UNIQUE CLUSTERED INDEX uc ON events (device_id, created_at); 
CREATE UNIQUE CLUSTERED INDEX uc ON multimedia (device_id, created_at); 

Si vous avez vraiment besoin de faire respecter le caractère unique du champ id, créer un index unique nonclustered pour cette colonne sur chaque table (mais il provoquera la commande de suppression de consommer plus de temps):

CREATE UNIQUE INDEX ix_id ON events (id); 
CREATE UNIQUE INDEX ix_id ON multimedia (id);