First I want to thank everyone who attended my December 5, 2019 webinar “Introduction to MySQL Query Tuning for DevOps“. Recording and slides are available on the webinar page.
Here are answers to the questions from participants which I was not able to provide during the webinar.
Q: How to find stored execution plans and optimizer metadata stored in mysql data dictionary (i.e. PS, IS, sys schema)?
A: The Optimizer creates the query execution plan each time when MySQL Server executes the query. These plans are never stored.
However, some information, used by the optimizer, to create the execution plan, is stored and available. It includes.
|
1 |
mysql> show index from employees;<br>+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+<br>| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |<br>+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+<br>| employees | 0 | PRIMARY | 1 | emp_no | A | 299556 | NULL | NULL | | BTREE | | |<br>| employees | 1 | first_name | 1 | first_name | A | 1196 | NULL | NULL | | BTREE | | |<br>| employees | 1 | first_name | 2 | last_name | A | 280646 | NULL | NULL | | BTREE | | |<br>+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+<br>3 rows in set (0,00 sec)<br> |
|
1 |
mysql> select * from information_schema.statistics where TABLE_SCHEMA='employees' and table_name='employees';<br>+---------------+--------------+------------+------------+--------------+------------+--------------+-------------+-----------+-------------+----------+--------+----------+------------+---------+---------------+<br>| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | NON_UNIQUE | INDEX_SCHEMA | INDEX_NAME | SEQ_IN_INDEX | COLUMN_NAME | COLLATION | CARDINALITY | SUB_PART | PACKED | NULLABLE | INDEX_TYPE | COMMENT | INDEX_COMMENT |<br>+---------------+--------------+------------+------------+--------------+------------+--------------+-------------+-----------+-------------+----------+--------+----------+------------+---------+---------------+<br>| def | employees | employees | 0 | employees | PRIMARY | 1 | emp_no | A | 299556 | NULL | NULL | | BTREE | | |<br>| def | employees | employees | 1 | employees | first_name | 1 | first_name | A | 1196 | NULL | NULL | | BTREE | | |<br>| def | employees | employees | 1 | employees | first_name | 2 | last_name | A | 280646 | NULL | NULL | | BTREE | | |<br>+---------------+--------------+------------+------------+--------------+------------+--------------+-------------+-----------+-------------+----------+--------+----------+------------+---------+---------------+<br>3 rows in set (0,00 sec)<br> |
|
1 |
mysql> select * from mysql.innodb_index_stats where database_name='employees' and table_name='employees';<br>+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+<br>| database_name | table_name | index_name | last_update | stat_name | stat_value | sample_size | stat_description |<br>+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+<br>| employees | employees | PRIMARY | 2019-12-12 18:22:40 | n_diff_pfx01 | 299556 | 20 | emp_no |<br>| employees | employees | PRIMARY | 2019-12-12 18:22:40 | n_leaf_pages | 886 | NULL | Number of leaf pages in the index |<br>| employees | employees | PRIMARY | 2019-12-12 18:22:40 | size | 929 | NULL | Number of pages in the index |<br>| employees | employees | first_name | 2019-12-12 21:49:02 | n_diff_pfx01 | 1196 | 20 | first_name |<br>| employees | employees | first_name | 2019-12-12 21:49:02 | n_diff_pfx02 | 280646 | 20 | first_name,last_name |<br>| employees | employees | first_name | 2019-12-12 21:49:02 | n_diff_pfx03 | 298471 | 20 | first_name,last_name,emp_no |<br>| employees | employees | first_name | 2019-12-12 21:49:02 | n_leaf_pages | 460 | NULL | Number of leaf pages in the index |<br>| employees | employees | first_name | 2019-12-12 21:49:02 | size | 545 | NULL | Number of pages in the index |<br>+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+<br>8 rows in set (0,01 sec)<br> |
|
1 |
mysql> select HISTOGRAM from information_schema.column_statistics<br> -> where table_name='example'G<br>*************************** 1. row ***************************<br>HISTOGRAM: {"buckets": [[1, 0.6], [2, 0.8], [3, 1.0]],<br>"data-type": "int", "null-values": 0.0, "collation-id": 8,<br>"last-updated": "2018-11-07 09:07:19.791470",<br>"sampling-rate": 1.0, "histogram-type": "singleton",<br>"number-of-buckets-specified": 3}<br>1 row in set (0.00 sec) |
optimizer_trace_limit queries. This data stored in memory, disabled by default and available in the
information_schema.optimizer_trace table:|
1 |
mysql> set optimizer_trace=1;<br>Query OK, 0 rows affected (0,00 sec)<br><br>mysql> select count(*) from employees where first_name like 'A%';<br>+----------+<br>| count(*) |<br>+----------+<br>| 22039 |<br>+----------+<br>1 row in set (0,16 sec)<br><br>mysql> select * from information_schema.optimizer_traceG<br>*************************** 1. row ***************************<br> QUERY: select count(*) from employees where first_name like 'A%'<br> TRACE: {<br> "steps": [<br> {<br> "join_preparation": {<br> "select#": 1,<br> "steps": [<br> {<br> "expanded_query": "/* select#1 */ select count(0) AS `count(*)` from `employees` where (`employees`.`first_name` like 'A%')"<br> }<br> ]<br> }<br> },<br> {<br> "join_optimization": {<br> "select#": 1,<br> "steps": [<br> {<br>... |
Q: Is it possible to list all possible plans available to optimizer for an individual query? how?
A: Since query execution plans created each time when the query is executed it is not possible to list them all.
Q: How to clear an existing plan for a particular query or all optimizer metadata from the data dictionary?
A: Since query execution plans are not stored anywhere, there is no need to clear them.
Q: Hey there, I have been working with mysql for a long time, now I want to make a system that will have complex queries with a combination of group by columns, I want them to get completed in a couple of seconds and use the lowest ram, your advise may be helpful.
A: This is a complicated question. I recommend you to learn how MySQL can use indexes for GROUP BY . Start from “GROUP BY Optimization” chapter of the MySQL User Reference Manual.
Resources
RELATED POSTS