web-dev-qa-db-fra.com

En utilisant l'index, en utilisant temporaire, en utilisant filesort - comment résoudre ce problème?

Je travaille sur un système de suivi des événements qui utilise une poignée de tables de recherche ainsi que la table de journalisation principale. Dans un rapport que j'écris, un objet peut être sélectionné pour afficher des statistiques. L'interface affiche tous les objets par ordre décroissant d'importance (c.-à-d., Hits).

Le schéma pour les deux tables (légèrement réduit, mais vous obtenez l'essentiel):

CREATE TABLE IF NOT EXISTS `event_log` (
  `event_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(5) DEFAULT NULL,
  `object_id` int(5) DEFAULT NULL,
  `event_date` datetime DEFAULT NULL,
  PRIMARY KEY (`event_id`),
  KEY `user_id` (`user_id`),
  KEY `object_id` (`object_id`)
);

CREATE TABLE IF NOT EXISTS `lookup_event_objects` (
  `object_id` int(11) NOT NULL AUTO_INCREMENT,
  `object_desc` varchar(255) NOT NULL,
  PRIMARY KEY (`object_id`)
);

La requête avec laquelle j'ai des problèmes est ci-dessous. Cela fonctionne très bien avec ma table de ~ 100 entrées, mais EXPLAIN m'inquiète un peu.

    explain SELECT 
            el.object_id, 
            leo.object_desc, 
            COUNT(el.object_id) as count_rows
        FROM 
            event_log el 
            LEFT JOIN lookup_event_objects leo ON leo.object_id = el.object_id
        GROUP BY 
            el.object_id
        ORDER BY 
            count_rows DESC,
            leo.object_desc ASC

Résultats: Using index; Using temporary; Using filesort

Alors - quel est le problème avec mon schéma et/ou ma requête pour que MySQL se replie sur temporary et filesort? Ou est-il aussi optimisé que possible avec ORDER BY?

46
a coder

Eh bien, le doc donne les raisons exactes quand "Utilisation temporaire" apparaîtra:

Des tables temporaires peuvent être créées dans des conditions telles que celles-ci:

S'il existe une clause ORDER BY et une autre clause GROUP BY, ou si ORDER BY ou GROUP BY contient des colonnes de tables autres que la première table de la file d'attente de jointure, une table temporaire est créée.

DISTINCT combiné avec ORDER BY peut nécessiter une table temporaire.

Si vous utilisez l'option SQL_SMALL_RESULT, MySQL utilise une table temporaire en mémoire, sauf si la requête contient également des éléments (décrits plus loin) qui nécessitent un stockage sur disque.

Une analyse rapide montre que vous souffrez du n ° 1.

Et ce blog de 2009 dit que "l'utilisation de filesort" signifie que le tri ne peut pas être effectué avec un index. Puisque vous commandez par un champ calculé, cela va être vrai aussi.

C'est donc ce qui "ne va pas".

82
Alain Collins

Mis à jour pour MySQL 5.7 ( src ):

Le serveur crée des tables temporaires dans des conditions telles que celles-ci:

  • Évaluation des déclarations UNION, à quelques exceptions près décrites plus loin.

  • Évaluation de certaines vues, telles que celles qui utilisent l'algorithme TEMPTABLE, UNION ou l'agrégation.

  • Évaluation des tables dérivées (sous-requêtes dans la clause FROM).

  • Tables créées pour la matérialisation de sous-requête ou de semi-jointure (voir Section 8.2.2, "Optimisation des sous-requêtes, des tables dérivées et des références de vue").

  • Évaluation des instructions contenant une clause ORDER BY et une clause GROUP BY différente, ou pour lesquelles ORDER BY ou GROUP BY contient des colonnes de tables autres que la première table de la file d'attente de jointure.

  • L'évaluation de DISTINCT combinée à ORDER BY peut nécessiter une table temporaire.

  • Pour les requêtes qui utilisent le modificateur SQL_SMALL_RESULT, MySQL utilise une table temporaire en mémoire, sauf si la requête contient également des éléments (décrits plus loin) qui nécessitent un stockage sur disque.

  • Pour évaluer les instructions INSERT ... SELECT qui sélectionnent et insèrent dans la même table, MySQL crée une table temporaire interne pour contenir les lignes de SELECT, puis insère ces lignes dans la table cible. Voir Section 13.2.5.1, "INSERT ... SELECT Syntax".

  • Évaluation des instructions UPDATE à plusieurs tables.

  • Évaluation des expressions GROUP_CONCAT () ou COUNT (DISTINCT).

7
Erwin Wessels

Ce sont les conditions suivantes dans lesquelles les tables temporaires sont créées. Les requêtes UNION utilisent des tables temporaires.

Certaines vues nécessitent des tables temporaires, telles que celles évaluées à l'aide de l'algorithme TEMPTABLE, ou qui utilisent UNION ou l'agrégation.

S'il existe une clause ORDER BY et une autre clause GROUP BY, ou si ORDER BY ou GROUP BY contient des colonnes de tables autres que la première table de la file d'attente de jointure, une table temporaire est créée.

DISTINCT combiné avec ORDER BY peut nécessiter une table temporaire.

Si vous utilisez l'option SQL_SMALL_RESULT, MySQL utilise une table temporaire en mémoire, sauf si la requête contient également des éléments (décrits plus loin) qui nécessitent un stockage sur disque.

Suivez ce lien par mysql: http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html

1
Aman Aggarwal