MySQL剖析单条查询

使用SHOW PROFILE

SHOW PROFILE命令默认是禁用的,可以通过以下命令修改

SET profiling=1;

当一条查询提交给服务器时,,此工具会记录剖析信息到一张临时表,并且给查询一个从1开始的整数标识符
SELECT * from poem_config;

```sql SHOW PROFILES; ```
结果
master >show profiles;
+----------+------------+---------------------------+
| Query_ID | Duration   | Query                     |
+----------+------------+---------------------------+
|        1 | 0.00030575 | select * from poem_config |
+----------+------------+---------------------------+

这里可以看到查询执行的精确时间,这个时间是总的时间
SHWO PROFILE FOR QUERY 1

结果
master >show profile for query 1;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000057 |
| checking permissions | 0.000008 |
| Opening tables       | 0.000017 |
| init                 | 0.000021 |
| System lock          | 0.000009 |
| optimizing           | 0.000004 |
| statistics           | 0.000012 |
| preparing            | 0.000011 |
| executing            | 0.000003 |
| Sending data         | 0.000121 |
| end                  | 0.000005 |
| query end            | 0.000007 |
| closing tables       | 0.000008 |
| freeing items        | 0.000013 |
| cleaning up          | 0.000011 |
+----------------------+----------+

剖析报告给出了查询执行的每个步骤及其花费的时间,通过这个报告我们可以确定哪些步骤耗时较长,从而找到对应的优化方法。


使用SHOW STATUS

MySQL的SHOW STATUS命令返回一些计数器,这些计数器可以显示某些活动如读索引的频繁程度,但无法给出消耗了多少时间。

尽管SHOW STATUS无法提供基于时间的统计,但对于执行完查询后观察某些计数器的值还是有帮助的。有时候我们可以从这些值里面猜测哪些代价较高或者消耗的时间较多。

最有用的计数器包括句柄计数器(handler counter)、临时文件和表计数器


示例:

我们先将临时会话级别的计数器重置为0,然后执行查询,再检查计数器的结果

FLUSH STATUS;

SELECT * FROM poem_config;

SHOW STATUS WHERE Variable_name LIKE 'Handler%'
OR Variable_name LIKE 'Created%';

结果

master >SHOW STATUS WHERE Variable_name LIKE 'Handler%'
    -> OR Variable_name LIKE 'Created%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Created_tmp_disk_tables    | 0     |
| Created_tmp_files          | 0     |
| Created_tmp_tables         | 0     |
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_external_lock      | 2     |
| Handler_mrr_init           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 1     |
| Handler_read_key           | 1     |
| Handler_read_last          | 0     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 20    |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+

从结果你可以看到,查询没有使用临时表,并且有较多的没有用到索引的读操作(Handler_read_rnd_next),Handler_read_rnd_next的值为20,整个表里的数据也是20条,说明是全表扫描。

未完待续...

posted @ 2019-12-22 22:03  乘月归  阅读(403)  评论(0编辑  收藏  举报