La sortie EXPLAIN suggère que mon index n'est pas utilisé

9

J'ai configuré ma table avec un index uniquement sur done_status (done_status = INT):

entrez la description de l'image ici

Quand j'utilise:

EXPLAIN SELECT * FROM reminder  WHERE done_status=2

Je récupère ceci:

id select_type type de table possible_keys key key_len ref lines Extra
1 RAPPEL SIMPLE TOUT done_status NULL NULL NULL 5 Utilisation de where

Mais quand j'émets cette commande:

EXPLAIN SELECT * FROM reminder  WHERE done_status=1

Je reçois ce qui suit:

id select_type type de table possible_keys key key_len ref lines Extra
1 SIMPLE rappel ref done_status done_status 4 const 2   

Le EXPLAINme montre qu'il utilise 5 lignes, la deuxième fois 2 lignes.

Je ne pense pas que l'index soit utilisé, si je l'ai bien compris la première fois, il devrait me donner 3 lignes. Qu'est-ce que je fais mal?

SHOW INDEX FROM reminder:

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Commentaire Index_comment
rappel 1 done_status 1 done_status A 5 NULL NULL BTREE

expliquer étendu:

id select_type type de table possible_keys clé key_len ref lignes filtrées Extra
1 SIMPLE rappel ref done_status done_status 4 const 2100.00

show warnings n'a rien montré d'intéressant.

TasostheGreat
la source
Croyez-moi, l'index fonctionne. Mais je ne peux rien voir facilement dans votre capture d'écran - pouvez-vous faire un "show index from yourtable"
ouais édité ma question
veuillez utiliser glorify \ G pour le schéma et expliquer le résultat du plan, il devrait être plus lisible
ajreal
Par intérêt, pouvez-vous répéter avec un "expliquer étendu" et un "afficher les avertissements" cela montrera le vrai SQL mysql choisit
@ajreal qu'est-ce que glorify?

Réponses:

4

Vous comprenez mal ce qu'est le champ "lignes". C'est le nombre de lignes que mysql estime devoir lire pour satisfaire votre requête. Cette valeur peut être assez inexacte. Cela ne signifie pas que c'est le nombre de lignes dans le résultat - ou le nombre réel de lignes lues par mysql


la source
Donc? Où ai-je dit que c'était le cas? Qu'est-ce que l'optimiseur choisit? L'index fonctionne toujours.
@ajreal Cela ne signifie pas pour autant que l'indice est cassé. Seul l'optimiseur choisit (dans son esprit) la manière la plus efficace d'interroger les données. J'ai supposé que l'OP s'attendait à ce que la colonne des lignes dans EXPLAIN soit exacte. Cela ne signifie pas que l'index est cassé - juste que mysql choisit de ne pas l'utiliser (probablement).
1
@ajreal: Je manque quelque chose dans vos points. La colonne des lignes d'une explication n'a rien à voir avec les index non? Mysql choisit de ne pas utiliser l'index (peut-être que toutes les données sont sur une seule page). Vous n'êtes pas sûr de comprendre votre point? L'optimisation des requêtes sur une table à 5 lignes va produire des résultats «bizarres» car peu importe comment vous optimisez.
Dans ce cas, peu importe l'index choisi par l'optimiseur? Il n'y a rien de mal avec l'index lui-même, car l'optimiseur avait l'impression qu'il n'en avait pas besoin - qu'importe?
3

La première plaine d'exécution ne fait pas forcément usage de l'index,
il se pourrait que l'information_schema.statistics sur l'index ne rattrape pas les données après quelques opérations d'écriture, ou que la table ne soit pas accessible depuis longtemps.

comme expliqué ici: - D'où MySQL Query Optimizer lit-il les statistiques d'index?

pour le deuxième plan d'exécution, il semble que information_schema.statistics rattrape et corrige déjà le problème de cardinalité NULL.

Par conséquent, exécutez la requête en fonction de l'optimiseur d'index.

Pour une table avec de petites rangées, peu importe.
Mais les données vont augmenter, le développeur doit toujours vérifier cela
et effectuer la table d'analyse nécessaire lorsque la cardinalité de rencontre est nulle sur l'index.

ajreal
la source
0

Le premier plan d'exécution n'utilise pas d'index.

Depuis le site Web de référence MySQL :

Parfois, MySQL n'utilise pas d'index, même s'il est disponible. Une situation dans laquelle cela se produit est lorsque l'optimiseur estime que l'utilisation de l'index nécessiterait que MySQL accède à un très grand pourcentage des lignes de la table. (Dans ce cas, une analyse de table est susceptible d'être beaucoup plus rapide car elle nécessite moins de recherches.) Cependant, si une telle requête utilise LIMIT pour récupérer uniquement certaines lignes, MySQL utilise de toute façon un index, car il peut trouver beaucoup plus rapidement les quelques lignes à renvoyer dans le résultat.

Si votre table ne contient que 5 lignes et que votre requête en sélectionne 3, l'optimiseur MySQL suppose qu'il est plus efficace d'analyser la table entière.

Matthew Sammut
la source