Como obtenho o plano de execução para uma visualização?

9

Eu tenho um esquema com várias visualizações. Preciso verificar os planos de execução para garantir que os índices apropriados estejam em vigor e em uso.

Como eu faço isso?

Eu prefiro não ter que copiar e colar a saída do show create view <viewname>into explain, especialmente porque algumas das visualizações são construídas sobre outras e isso seria bastante trabalhoso.

Matt Fenwick
fonte
11
Observe que o plano de execução pode ser diferente quando o VIEW é usado em consultas da vida real, pois depende das cláusulas WHERE e de outras cláusulas na consulta, selecionadas no VIEW. Embora o MySQL seja bastante ruim na otimização de VIEWs, ele possui algumas otimizações nas quais as condições são reduzidas, por exemplo.
Janes
@ Jannes bom ponto, eu não considerei esse aspecto. É seguro assumir que o plano de execução select * from <view_name>será compatível?
Matt Fenwick
11
Sim, tanto quanto eu sei. Se você quiser que o mysql use um índice no campo1, selecione * em <nome-da-vista>, onde campo1 = 10 , você deve manter a visualização realmente simples. Nenhum GROUP BY ou UNION, por exemplo. Eu acho que você poderia dizer que o plano de execução que você está vendo é uma das piores situações, pois só poderia melhorar se o mysql encontrar uma otimização para usar.
Janes

Respostas:

7

Isto é o que eu tentei pela primeira vez:

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       |       |
+---------+------------+------+-----+---------+-------+

Obviamente, isso não funciona - é o mesmo que fazer describe view_name.

No entanto, select * from view_nameparece funcionar:

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
fonte
+1 para uma resposta clara e mais simples. Eu ajustei minha resposta com base na sua. Você deve aceitar sua resposta neste caso.
RolandoMySQLDBA 22/03
7

Use a tabela information_schema.views

Isso irá gerar o EXPLAIN para todas as visualizações

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

Isso irá gerar o EXPLAIN para todas as visualizações no banco de dados mydb

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

De uma chance !!!

ATUALIZAÇÃO 22-03-2012 11:30 EDT

@ MattFenwick, sua resposta é muito mais simples que a minha. Aqui está um exemplo que experimentei no meu PC executando o MySQL 5.5.12. Executei EXPLAIN na versão SELECT da sua resposta e no EXPLAIN gerado a partir da minha resposta:

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>

Ambos produziram o mesmo plano EXPLAIN. Vou mudar minha resposta para implementar seu caminho. Você recebe um +1 de mim, embora seja +2 por simplicidade. Você deve seguir em frente e aceitar sua própria resposta.

Aqui está um factóide interessante sobre as visualizações no MySQL: Uma visualização é representada em dois lugares no banco de dados information_schema

Isso irá gerar o EXPLAIN para todas as visualizações

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

Isso irá gerar o EXPLAIN para todas as visualizações no banco de dados 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
fonte
+1 por mostrar que o plano de execução é o mesmo nos dois sentidos!
Matt Fenwick