最近的某一天,我在某平台看到一篇文章,是关于SQL优化的,
其中,讲到如何查看SQL执行情况,常用的工具有EXPLAIN查看执行计划,
profiling查看执行时间,于是,我打算实战一下,
我使用的MySQL版本为5.7.34,发现,配置profiling属性时,提示该方法将来会被移除,
现在已处于Deprecated状态(不过还能用),但是,我并没有尝试使用,
因为,MySQL官方既然废弃profiling功能,肯定会有替代的方案,
于是,开始搜索,找到了替代方案:Performance Schema(MySQL5.6.x开始支持),
当我搜索中文如何使用Performance Schema时,只有一点点理论上的语句,
并没有完整的测试案例,如通过Performance Schema检测具体某一条SQL的执行时间,
所以,参考官网文档,理论和实践相结合,使用Performance Schema实战监控SQL相关执行过程,
分享如下,提供实践参考案例,帮助读者理解和使用Performance Schema。
官方文档:https://dev.mysql.com/doc/refman/5.6/en/performance-schema.html
Performance Schema为提供访问服务器执行信息而设计,同时消耗最少的服务器资源,具体设计原则如下:
-- 查看MySQL版本信息
SHOW variables like "%version%";
-- 查看profile
SHOW variables like "%prof%";
profiling为OFF,此时无法查看SQL执行时间。

-- 开启profiling
set profiling=1;

开启profiling之后,发现,该MySQL版本(5.7.34)提示profiling已标识为deprecated,未来MySQL版本将移除该功能,如下图所示。

于是,搜索了一下相关信息,在Github上发现profile未来将被删除,使用Performance Schema替代,github截图如下图所示。
https://github.com/phpmyadmin/phpmyadmin/issues/15209

-- 查看performance schema
SHOW VARIABLES LIKE 'performance_schema';
由结果可知,performance schema默认开启。

-- 查询等待事件采集器状态
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait%';

-- 开启等待事件采集器
UPDATE performance_schema.setup_instruments SET ENABLED='YES', TIMED='YES' WHERE NAME LIKE 'wait%';

-- 查询等待事件消费者状态
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%wait%';

-- 开启等待事件消费者
UPDATE performance_schema.setup_consumers SET ENABLED='YES' WHERE NAME LIKE '%wait%';

-- 查询
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%statement/%';

-- 更新
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%statement/%';

-- 查询
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%stage/%';

-- 更新
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%stage/%';

-- 查看消费者事件状态
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%events_statements_%';

-- 开启消费者事件状态
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%events_statements_%';

-- 查看alter
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%events_stages_%';

--
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%events_stages_%';

-- 查询测试
SELECT * FROM db_monkey_run.tb_sys_user where user_id = "0x001";
先看下执行计划:
-- 查看执行计划
EXPLAIN SELECT * FROM db_monkey_run.tb_sys_user where user_id = "0x001";
执行计划结果如下图所示。由结果可知,该条SQL为简单查询,无分区,type为ref可知使用非主键索引等值扫描。

执行一条SQL后,Performance Schema会生成该条SQL的事件,通过事件ID可以查询该条SQL的相关执行信息,
查询该SQL的事件语句如下:
-- 查看sql对应的event_id
SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT
FROM performance_schema.events_statements_history_long WHERE SQL_TEXT like '%0x001%';
由上述语句可知,将时间TIMER_WAIT处理为秒,保留6位有效数字,
Performance Schema中时间单位为皮秒,1秒=10^12皮秒,
因此,TIMER_WAIT除以10^12。
查询SQL的结果如下图所示,事件ID:EVENT_ID为1286,可根据该事件ID查询SQL执行信息,
该条SQL总耗时为0.000444秒。

上面获取SQL执行的事件ID为1286,因此,根据该ID查询SQL各阶段执行时间,
语句如下:
-- 根据event_id查询各阶段耗时
SELECT event_name AS Stage, TRUNCATE(TIMER_WAIT/1000000000000,6) AS Duration
FROM performance_schema.events_stages_history_long WHERE NESTING_EVENT_ID=1286;
SQL各阶段耗时如下图所示。由图可知,SQL执行共拆解为15个阶段,
其中,
SQL
优化耗时:optimizing为0.000008秒。
准备耗时:preparing为0.000009秒。
执行耗时:executing为0.000002秒。
发送数据:Sending data为0.000054秒。
由此可知,一条SQL完整生命周期耗时不单单是执行SQL耗时,还包括打开表、优化SQL、关闭表、发送数据等过程,
SQL的优化可以针对不同的阶段进行,如果SQL自动优化时间长,可以重新设计SQL等。

| 序号 | 阶段 | 描述 |
|---|---|---|
| 1 | starting | 启动 |
| 2 | checking permissions | 检查权限 |
| 3 | Opening tables | 打开表 |
| 4 | init | 初始化 |
| 5 | System lock | 系统锁 |
| 6 | optimizing | 优化SQL |
| 7 | statistics | 统计 |
| 8 | preparing | 准备SQL |
| 9 | executing | 执行SQL |
| 10 | Sending data | 发送数据 |
| 11 | end | 发送结束 |
| 12 | query end | 查询结束 |
| 13 | closing tables | 关闭表 |
| 14 | freeing items | 释放item |
| 15 | cleaning up | 清理 |
核心:
(1)Performance Schema用于监控SQL执行,如各阶段耗时、阶段的锁等待、索引访问、物理I/O和逻辑I/O等;
(2)Performance Schema中的表是内存表,随MySQL服务器启动载入数据,关闭清除数据,资源消耗少,配置即时生效;
(3)Performance Schema的异常不影响SQL的正常执行;
(4)使用Performance Schema需要配置采集器和消费者,具体要开启:events_statements_history_long和events_stages_history_long等。
11:03:46 UPDATE performance_schema.setup_instruments SET ENABLED=‘YES’, TIMED=‘YES’ WHERE NAME LIKE ‘wait%’ Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. 0.000 sec
-- 关闭安全更新
SET SQL_SAFE_UPDATES=0;