Jak uzyskać plan wykonania widoku?

9

Mam schemat z wieloma widokami. Muszę sprawdzić plany wykonania, aby upewnić się, że odpowiednie indeksy są na miejscu i są używane.

Jak mam to zrobic?

Wolałbym nie kopiować i wklejać danych wyjściowych show create view <viewname>do explain, zwłaszcza, że ​​niektóre widoki są zbudowane na innych widokach, co byłoby dość uciążliwe.

Matt Fenwick
źródło
1
Należy pamiętać, że plan wykonania może być inny, gdy WIDOK jest używany w zapytaniach rzeczywistych, ponieważ zależy od GDZIE i innych klauzul w zapytaniu wybieranych z WIDOKU. Chociaż MySQL jest dość kiepski w optymalizacji WIDOKÓW, ma pewne optymalizacje, na przykład warunki są spychane w dół.
Jannes
@Jannes dobry punkt, nie rozważałem tego aspektu. Czy można bezpiecznie założyć, że plan wykonania z select * from <view_name>pasuje?
Matt Fenwick
1
Tak, o ile mi wiadomo. Jeśli chcesz, aby mysql używał indeksu w polu 1, wybierz * z <nazwa_widoku> gdzie pole1 = 10, to musisz zachować widok naprawdę prosty. Na przykład brak GROUP BY lub UNION. Wydaje mi się, że można powiedzieć, że plan wykonania, na który patrzysz, jest najgorszym przypadkiem, ponieważ może być lepszy tylko wtedy, gdy mysql znajdzie optymalizację do użycia.
Jannes

Odpowiedzi:

7

Oto, co najpierw wypróbowałem:

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

Oczywiście to nie działa - to tak samo jak robienie describe view_name.

Jednak select * from view_namewydaje się działać:

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
źródło
+1 za wyraźną, prostszą odpowiedź. Dostosowałem odpowiedź na podstawie twojej. Powinieneś zaakceptować swoją odpowiedź na ten temat.
RolandoMySQLDBA
7

Skorzystaj z tabeli information_schema.views

Spowoduje to wygenerowanie WYJAŚNIENIA dla wszystkich widoków

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

Spowoduje to wygenerowanie WYJAŚNIENIA dla wszystkich widoków w bazie danych mydb

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

Spróbuj !!!

AKTUALIZACJA 22.03.2012 11:30 EDT

@MattFenwick, twoja odpowiedź jest o wiele prostsza niż moja. Oto przykład, który wypróbowałem na moim komputerze z systemem MySQL 5.5.12. Uruchomiłem EXPLAIN zarówno dla wersji SELECT z twojej odpowiedzi, jak i EXPLAIN wygenerowanej z mojej odpowiedzi:

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>

Obaj opracowali ten sam plan WYJAŚNIJ. Zmienię swoją odpowiedź, aby wdrożyć twój sposób. Dostajesz ode mnie +1, chociaż dla uproszczenia jest to +2. Powinieneś śmiało zaakceptować własną odpowiedź w tej sprawie.

Oto interesujący faktoid o WIDOKACH w MySQL: Widok jest reprezentowany w dwóch miejscach w bazie danych information_schema

Spowoduje to wygenerowanie WYJAŚNIENIA dla wszystkich widoków

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

lub

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

Spowoduje to wygenerowanie WYJAŚNIENIA dla wszystkich widoków w bazie danych 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

lub

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
źródło
+1 za pokazanie, że plan wykonania jest taki sam w obie strony!
Matt Fenwick