Comment obtenir le plan d'exécution d'une vue?

9

J'ai un schéma avec un certain nombre de vues. Je dois vérifier les plans d'exécution pour m'assurer que les index appropriés sont en place et utilisés.

Comment puis-je faire cela?

Je préfère ne pas avoir à copier et coller la sortie de show create view <viewname>dans explain, d'autant plus que certaines vues sont construites au-dessus d'autres vues et ce serait assez pénible.

Matt Fenwick
la source
1
Notez que le plan d'exécution peut être différent lorsque le VIEW est utilisé dans des requêtes réelles, car il dépend du WHERE et des autres clauses de la requête sélectionnant dans le VIEW. Bien que MySQL soit assez mauvais pour optimiser les VIEWs, il a quelques optimisations où les conditions sont poussées par exemple.
Jannes
@Jannes bon point, je n'ai pas considéré cet aspect. Est-il sûr de supposer que le plan d'exécution de select * from <view_name>correspondra?
Matt Fenwick
1
Ouais pour autant que je sache. Si vous voulez que mysql utilise un index sur field1 dans select * from <view-name> où field1 = 10 alors vous devez garder la vue vraiment simple. Pas de GROUP BY ou UNION par exemple. Je suppose que vous pourriez dire que le plan d'exécution que vous regardez est en quelque sorte la pire des situations dans la mesure où il ne pourrait s'améliorer que si mysql trouve une optimisation à utiliser.
Jannes

Réponses:

7

Voici ce que j'ai essayé pour la première fois:

mysql> explain view_name;
+---------+------------+------+-----+---------+-------+
| Field   | Type       | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| field1  | varchar(3) | YES  |     | NULL    |       |
| field2  | varchar(3) | YES  |     | NULL    |       |
| field3  | bigint(21) | NO   |     | 0       |       |
| field4  | bigint(21) | NO   |     | 0       |       |
+---------+------------+------+-----+---------+-------+

Évidemment, cela ne fonctionne pas - c'est la même chose que faire describe view_name.

Cependant, select * from view_namesemble fonctionner:

mysql> explain select * from view_name;
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra                           |
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
|  1 | PRIMARY     | <derived5> | ALL  | NULL          | NULL | NULL    | NULL |   18 |                                 |
|  1 | PRIMARY     | <derived3> | ALL  | NULL          | NULL | NULL    | NULL |  105 | Using where; Using join buffer  |
|  5 | DERIVED     | <derived6> | ALL  | NULL          | NULL | NULL    | NULL |   68 | Using temporary; Using filesort |
|  6 | DERIVED     | basetable  | ALL  | NULL          | NULL | NULL    | NULL |  928 | Using temporary; Using filesort |
|  3 | DERIVED     | <derived4> | ALL  | NULL          | NULL | NULL    | NULL |  386 | Using temporary; Using filesort |
|  4 | DERIVED     | basetable  | ALL  | NULL          | NULL | NULL    | NULL |  928 | Using temporary; Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+------+---------------------------------+
Matt Fenwick
la source
+1 pour une réponse claire et simple. J'ai ajusté ma réponse en fonction de la vôtre. Vous devez accepter votre réponse à ce sujet.
RolandoMySQLDBA
7

Utilisez la table information_schema.views

Cela va générer l'EXPLIQUER pour toutes les vues

mysql -uroot -p -AN -e"select concat('explain ',view_definition) from information_schema.views" > /root/ExplainViews.sql

Cela générera l'EXPLAIN pour toutes les vues de la base de données mydb

mysql -uroot -p -AN -e"select concat('explain ',view_definition) from information_schema.views where table_schema = 'mydb'" > /root/ExplainViews.sql

Essaie !!!

MISE À JOUR 2012-03-22 11:30 EDT

@MattFenwick, votre réponse est beaucoup plus simple que la mienne. Voici un exemple que j'ai essayé sur mon PC exécutant MySQL 5.5.12. J'ai exécuté EXPLAIN sur la version SELECT de votre réponse et sur l'EXPLAIN généré à partir de ma réponse:

mysql> explain select * from bigjoin;
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref           | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
|  1 | SIMPLE      | k     | index  | NULL          | PRIMARY | 4       | NULL          |   14 | Using index |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY       | PRIMARY | 4       | test.k.id_key |    1 | Using index |
|  1 | SIMPLE      | b     | ALL    | NULL          | NULL    | NULL    | NULL          |    4 |             |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
3 rows in set (0.00 sec)

mysql> explain select `a`.`id_key` AS `id_key1`,`b`.`id_key` AS `id_key2` from ((`test`.`idlist` `k` left join `test`.`id_key_table` `a` on((`k`.`id_key` = `a`.`id_key`))) left join `test`.`new_keys_to_load` `b` on((`k`.`id_key` = `b`.`id_key`)));
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref           | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
|  1 | SIMPLE      | k     | index  | NULL          | PRIMARY | 4       | NULL          |   14 | Using index |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY       | PRIMARY | 4       | test.k.id_key |    1 | Using index |
|  1 | SIMPLE      | b     | ALL    | NULL          | NULL    | NULL    | NULL          |    4 |             |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
3 rows in set (0.00 sec)

mysql>

Ils ont tous deux produit le même plan EXPLAIN. Je vais changer ma réponse pour mettre en œuvre votre chemin. Vous obtenez un +1 de moi bien que ce soit +2 pour plus de simplicité. Vous devriez continuer et accepter votre propre réponse à ce sujet.

Voici une factoïde intéressante sur les VIEWs dans MySQL: Une vue est représentée à deux endroits dans la base de données information_schema

Cela va générer l'EXPLIQUER pour toutes les vues

mysql -uroot -p -AN -e"select concat('explain select * from ',table_schema,'.',table_name,';') from information_schema.tables WHERE engine IS NULL" > /root/ExplainViews.sql

ou

mysql -uroot -p -AN -e"select concat('explain select * from ',table_schema,'.',table_name,';') from information_schema.views" > /root/ExplainViews.sql

Cela générera l'EXPLAIN pour toutes les vues de la base de données mydb

mysql -uroot -p -AN -e"select concat('explain select * from ',table_schema,'.',table_name,';') from information_schema.tables WHERE table_schema='mydb' AND engine IS NULL;" > /root/ExplainViews.sql

ou

mysql -uroot -p -AN -e"select concat('explain select * from ',table_schema,'.',table_name,';') from information_schema.views WHERE table_schema='mydb';" > /root/ExplainViews.sql
RolandoMySQLDBA
la source
+1 pour montrer que le plan d'exécution est le même dans les deux sens!
Matt Fenwick