Come posso ottenere il piano di esecuzione per una vista?


9

Ho uno schema con un numero di visualizzazioni. Devo controllare i piani di esecuzione per assicurarmi che gli indici appropriati siano presenti e utilizzati.

Come faccio a fare questo?

Preferirei non dover copiare e incollare l'output da show create view <viewname>dentro explain, specialmente perché alcune delle viste sono costruite sopra altre viste e questo sarebbe abbastanza doloroso.


1
Si noti che il piano di esecuzione potrebbe essere diverso quando VIEW viene utilizzato nelle query di vita reale, poiché dipende da WHERE e dalle altre clausole della query che selezionano da VIEW. Anche se MySQL non è abbastanza bravo nell'ottimizzare le VISUALIZZAZIONI, ha alcune ottimizzazioni in cui, ad esempio, le condizioni vengono abbassate.
Jannes,

@Jannes buon punto, non ho considerato questo aspetto. È sicuro supporre che il piano di esecuzione di select * from <view_name>corrisponderà?
Matt Fenwick,

1
Sì, per quanto ne so. Se vuoi che mysql usi un indice su field1 in select * da <view-name> dove field1 = 10, devi mantenere la vista davvero semplice. Nessun GROUP BY o UNION per esempio. Immagino che potresti dire che il piano di esecuzione che stai osservando è una specie della situazione peggiore in quanto potrebbe migliorare solo se mysql trova un'ottimizzazione da usare.
Jannes,

Risposte:


7

Questo è quello che ho provato per la prima volta:

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

Ovviamente questo non funziona - è lo stesso che fare describe view_name.

Tuttavia, select * from view_namesembra funzionare:

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

+1 per una risposta più chiara e semplice. Ho modificato la mia risposta in base alla tua. Dovresti accettare la tua risposta su questo.
RolandoMySQLDBA

7

Utilizzare la tabella information_schema.views

Questo genererà EXPLAIN per tutte le viste

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

Questo genererà EXPLAIN per tutte le viste nel database mydb

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

Provaci !!!

AGGIORNAMENTO 2012-03-22 11:30 EDT

@MattFenwick, la tua risposta è molto più semplice della mia. Ecco un esempio che ho provato sul mio PC con MySQL 5.5.12. Ho eseguito EXPLAIN sia sulla versione SELECT della tua risposta sia su EXPLAIN generato dalla mia risposta:

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>

Entrambi hanno prodotto lo stesso piano EXPLAIN. Cambierò la mia risposta per implementare la tua strada. Ricevi un +1 da me, sebbene sia +2 per semplicità. Dovresti andare avanti e accettare la tua risposta su questo.

Ecco un interessante aspetto delle VISTE in MySQL: Una vista è rappresentata in due punti nel database information_schema

Questo genererà EXPLAIN per tutte le viste

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

Questo genererà EXPLAIN per tutte le viste nel database 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

+1 per mostrare che il piano di esecuzione è lo stesso in entrambi i modi!
Matt Fenwick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.