D'où MySQL Query Optimizer lit-il les statistiques d'index?

14

J'essaie de déterminer d'où l'optimiseur MySQL obtient la liste des index disponibles pour une table lorsqu'il estime le coût de (prépare) une requête.

ivotron
la source
+1 pour cette bonne question, car les développeurs et les administrateurs de base de données doivent faire une pause et réfléchir à la façon dont les statistiques d'index sont compilées et stockées.
RolandoMySQLDBA
Pour référence, sur le site Web de la documentation MySQL: < dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> ANALYZE TABLEdétermine l' indice cardinalité (comme indiqué dans la colonne Cardinalité de SHOW INDEXsortie) en faisant huit plongées au hasard à chaque des arbres d'index et la mise à jour des estimations de cardinalité d'index en conséquence. Étant donné qu'il ne s'agit que d'estimations, des exécutions répétées de ANALYZE TABLE peuvent produire des nombres différents. Cela rend ANALYZE TABLErapide les tables InnoDB mais pas précis à 100% car il ne prend pas en compte toutes les lignes.
Chen Xie

Réponses:

6

La réponse directe à cela serait

information_schema.statistics

mysql> desc information_schema.statistics;
+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512)  | NO   |     |         |       |
| TABLE_SCHEMA  | varchar(64)   | NO   |     |         |       |
| TABLE_NAME    | varchar(64)   | NO   |     |         |       |
| NON_UNIQUE    | bigint(1)     | NO   |     | 0       |       |
| INDEX_SCHEMA  | varchar(64)   | NO   |     |         |       |
| INDEX_NAME    | varchar(64)   | NO   |     |         |       |
| SEQ_IN_INDEX  | bigint(2)     | NO   |     | 0       |       |
| COLUMN_NAME   | varchar(64)   | NO   |     |         |       |
| COLLATION     | varchar(1)    | YES  |     | NULL    |       |
| CARDINALITY   | bigint(21)    | YES  |     | NULL    |       |
| SUB_PART      | bigint(3)     | YES  |     | NULL    |       |
| PACKED        | varchar(10)   | YES  |     | NULL    |       |
| NULLABLE      | varchar(3)    | NO   |     |         |       |
| INDEX_TYPE    | varchar(16)   | NO   |     |         |       |
| COMMENT       | varchar(16)   | YES  |     | NULL    |       |
| INDEX_COMMENT | varchar(1024) | NO   |     |         |       |
+---------------+---------------+------+-----+---------+-------+
16 rows in set (0.01 sec)

Vous pouvez sélectionner à partir de cette table avec

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';

ou voir les statistiques en faisant

AFFICHER LES INDEX DE mydb.mytable;

Veuillez garder à l'esprit que ce tableau n'est pas toujours précis dans un environnement lourd en écriture. Vous devrez périodiquement exécuter ANALYZE TABLE sur toutes les tables MyISAM qui sont mises à jour fréquemment. Sinon, MySQL Query Optimizer, qui s'appuie sur information_schema.statistics, peut parfois faire de mauvais choix lors du développement de plans EXPLAIN pour les requêtes. Les statistiques d'index doivent être aussi à jour que possible.

ANALYZE TABLE n'a ABSOLUMENT AUCUN EFFET sur les tables InnoDB. Toutes les statistiques d'index pour InnoDB sont calculées à la demande au moyen de plongées dans les pages BTREE. Par conséquent, lorsque vous exécutez SHOW INDEXES FROM sur une table InnoDB, les cardinalités affichées sont toujours des approximations.

MISE À JOUR 2011-06-21 12:17 EDT

Pour des éclaircissements sur ANALYZE TABLE, permettez-moi de reformuler. Exécuter ANALYZE TABLE sur les tables InnoDB est complètement inutile. Même si vous avez exécuté ANALYZE TABLE sur une table InnoDB, le moteur de stockage InnoDB effectue des plongées dans l'index pour les approximations de cardinalité à maintes reprises, détruisant ainsi les statistiques que vous venez de compiler . En fait, Percona a effectué certains tests sur ANALYZE TABLE et est également arrivé à cette conclusion.

RolandoMySQLDBA
la source
5

Re: ANALYZE TABLE n'a ABSOLUMENT AUCUN EFFET sur les tables InnoDB.

Je ne sais pas si cette affirmation est vraie. Nous avons beaucoup lu et écrit des tables innodb et lorsque l'optimiseur mysql fait le mauvais choix, la sortie d'explication de la requête montre une mauvaise stratégie. et également SHOW INDEXES d'une table Innodb montre tant de variance dans leurs valeurs de cardinalité. Mais l'exécution d'une commande ANALYSER sur ces tables innodb corrige le plan d'explication et supprime également le comportement de variance de la cardinalité. Je ne sais pas si la commande ANALYZE table sur les tables Innodb aide tout le temps ou non mais dans notre cas, cela a aidé environ 99% du temps.

Nous avons complètement éliminé le mauvais choix de l'optimiseur mysql en incluant le "STRAIGHT_JOIN" dans nos requêtes. Cela a forcé l'optimiseur mysql à ne pas faire de mauvais choix ou à faire des choix, mais à suivre la condition JOIN de ce que nous avons défini dans la requête telle quelle.

Revathi
la source
J'ai mis à jour ma réponse pour mettre en évidence l'inutilité de ANALYZE TABLE sur les tables InnoDB.
RolandoMySQLDBA
Je suis d'accord avec votre réponse lorsque vous avez mentionné la variance de la cardinalité. C'est exactement ce que je disais quand j'ai dit des approximations de cardinalité.
RolandoMySQLDBA
J'avais également besoin de mentionner que l'utilisation d'indices dans les requêtes n'est pas toujours la meilleure chose à faire lorsque MySQL Query Optimizer a tendance à les éliminer parfois. Voici un lien vers ce qui se passe en interne pour les requêtes qui peuvent réellement faire disparaître des données dans certaines parties des plans de requête: dba.stackexchange.com/questions/1371/…
RolandoMySQLDBA
2

ANALYZE TABLE for MyISAM scanne l'intégralité de la table et reconstruit les statistiques, qui sont enregistrées (je pense) dans le fichier .MYI. Il est rarement nécessaire.

ANALYZE TABLE for InnoDB fait quelque chose - il fait la plongée mentionnée. Le problème est que cela peut aider, aggraver les choses ou (très probablement) ne fera aucune différence visible (sauf dans les cardinalités).

Les nouvelles versions promettent de permettre de changer les 8 sondes pas si aléatoires en (1) plus aléatoires, (2) vous permettant de changer le "8" (il y a des avantages et des inconvénients à cela!), Et (3) l'enregistrement à travers les redémarrages.

Conclusion: InnoDB ne l'a toujours pas «bien». Faites une ANALYSE quand vous en avez envie, mais ne retenez pas votre souffle.

Mise à jour

Reformuler ... ANALYZE TABLEa un effet temporaire (peut-être bénéfique, peut-être pas) sur les optimisations des tables InnoDB.

"Version plus récente": à partir de 5.6.6 (2012) et de MariaDB 10.1 (2014), les statistiques sont beaucoup mieux gérées et ANALYZEsont désormais (1) moins souvent nécessaires et (2) plus permanentes.

Rick James
la source