2010-08-20 6 views
2

j'ai une requête élémentaire qui prend trop de temps pour exécuter même sur de petites tables (< 100 000 lignes):Accélérer la requête avec JOIN, où, groupe par, et compter

select images.classification, count(boxes.id) 
from images 
join boxes on images.id = boxes.image_id 
where boxes.round = 0 
group by images.classification; 

Je indices sur les boîtes .round, boxes.image_id et images.classification (seulement varchar dans cette requête). Clés primaires sur boxes.id et images.id. Expliquer indique qu'il profite de l'index boxes.round. Les suppléments sont: Using where; Using temporary; Using filesort.

Est-il possible d'accélérer cette requête? Comment?

Si cela est important, le serveur est MySQL 5.1 avec des tables MyISAM.

(Cette question est similaire à How to speed up "select count(*)" with "group by" and "where"?)


pleine EXPLAIN:

mysql> explain select images.classification, count(boxes.id) from images join boxes on images.id = boxes.image_id where boxes.round = 0 group by images.classification; 

| 1 | SIMPLE  | boxes | ref | ix_boxes_image_id,ix_boxes_round | ix_boxes_round | 5  | const      | 64162 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | images | eq_ref | PRIMARY          | PRIMARY    | 4  | vatic.boxes.image_id |  1 |            | 
+0

Pourriez-vous poster la sortie du 'EXPLAIN'? – Piskvor

+0

@Piskvor, ajouté. – carl

+0

Merci, c'est un élément de données plutôt crucial. – Piskvor

Répondre

2

Ajouter un index sur (images.id, images.classification) - qui devrait vous donner

  • un index pour la jointure. Vous avez déjà via la clé primaire, mais vous aurez également:
  • le même indice utilisable comme un indice de recouvrement
  • le même indice pour la clause de regroupement

ajouter également un index sur (boxes.image_id,boxes.round):

    index
  • pour la jointure
  • indice de couverture pour le COUNT (voir ci-dessous)

A propos de la clause COUNT: si vous n'avez pas NULL s dans boxes.id (en supposant que non), vous pouvez le remplacer par COUNT(boxes.image_id) afin que nous puissions obtenir un peu plus d'utilisation de l'index de prev. paragraphe.

Encore une fois, vérifiez avec EXPLAIN, mais je dirais que ces étapes devraient vous permettre d'avoir un meilleur plan d'exécution.

+1

Les extras: 'Using where' - ne peut pas comprendre toutes les conditions seulement des index - doit regarder dans les tables appropriées pour évaluer WHERE (plus lent); 'Using temporary' - besoin de créer une table de résultats temporaire pour cela (va ralentir avec de grandes tables); 'Using using files'' - la table temporaire est trop grande pour tenir dans la mémoire, l'échangera sur le disque (l'accès au disque est lent) – Piskvor

0

Ajouter un index images.id.

+1

images.id est une clé primaire. – carl

0

Serait-il possible d'utiliser un nombre entier pour images.classification au lieu d'un varchar?

+0

Cela pourrait être possible, mais cela nécessiterait une grande migration pour moi lorsque cette requête sera mise en ligne. – carl

+0

Bon point, INT est généralement plus rapide que VARCHAR. – Piskvor