¿Cómo obtengo el plan de ejecución para una vista?

9

Tengo un esquema con varias vistas. Necesito verificar los planes de ejecución para asegurarme de que los índices apropiados estén en su lugar y sean utilizados.

¿Cómo hago esto?

Yo preferiría no tener que copiar y pegar la salida desde show create view <viewname>dentro explain, sobre todo porque algunas de las vistas se construyen en la parte superior de otros puntos de vista y esto sería una gran dolor.

Matt Fenwick
fuente
1
Tenga en cuenta que el plan de ejecución puede ser diferente cuando VIEW se usa en consultas de la vida real, ya que depende de WHERE y otras cláusulas en la consulta que se selecciona de VIEW. Aunque MySQL es bastante malo para optimizar VIEWs, tiene algunas optimizaciones en las que las condiciones se reducen, por ejemplo.
Jannes
@Jannes buen punto, no consideré ese aspecto. ¿Es seguro asumir que el plan de ejecución select * from <view_name>coincidirá?
Matt Fenwick
1
Sí, hasta donde yo sé. Si desea que mysql use un índice en el campo1 en select * from <view-name> donde field1 = 10, entonces debe mantener la vista realmente simple. No GROUP BY o UNION por ejemplo. Supongo que podría decir que el plan de ejecución que está viendo es una de las peores situaciones, ya que solo podría mejorar si mysql encuentra una optimización para usar.
Jannes

Respuestas:

7

Esto es lo que probé por primera 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, esto no funciona, es lo mismo que hacer describe view_name.

Sin embargo, 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
fuente
+1 para una respuesta clara y más simple. Ajusté mi respuesta según la tuya. Deberías aceptar tu respuesta en este caso.
RolandoMySQLDBA
7

Use la tabla information_schema.views

Esto generará la EXPLICACIÓN para todas las vistas.

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

Esto generará la EXPLICACIÓN para todas las vistas en la base de datos mydb

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

Darle una oportunidad !!!

ACTUALIZACIÓN 2012-03-22 11:30 EDT

@MattFenwick, su respuesta es mucho más simple que la mía. Aquí hay un ejemplo que probé en mi PC con MySQL 5.5.12. Ejecuté EXPLAIN tanto en la versión SELECT de su respuesta como en EXPLAIN generado a partir de mi respuesta:

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 produjeron el mismo plan EXPLICAR. Cambiaré mi respuesta para implementar tu camino. Obtienes un +1 de mí, aunque es +2 por simplicidad. Debes seguir adelante y aceptar tu propia respuesta en este caso.

Aquí hay un hecho interesante sobre VIEWs en MySQL: una vista se representa en dos lugares en la base de datos information_schema

Esto generará la EXPLICACIÓN para todas las vistas.

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

o

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

Esto generará la EXPLICACIÓN para todas las vistas en la base de datos 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

o

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
fuente
¡+1 por mostrar que el plan de ejecución es el mismo en ambos sentidos!
Matt Fenwick