查不到 parsing/optimization 阶段数据是因为 performance schema 默认仅启用 statement/sql/select 等语句级 instrument,stage/sql/% 类阶段事件需手动启用:update performance_schema.setup_instruments set enabled='yes', timed='yes' where name like 'stage/sql/%';

能直接定位 SQL 解析、优化、执行、排序等阶段的耗时和资源消耗,但必须手动开启对应 instrument,否则 events_stages_history 等表全为空。
为什么查不到 parsing/optimization 阶段数据?
Performance Schema 默认只开启语句级(statement/sql/select)采集,不开启内部阶段事件。阶段事件(如 stage/sql/Sorting result)由独立的 instruments 控制,需显式启用:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'stage/sql/%';- 特别注意:
stage/sql/Opening tables、stage/sql/Creating sort index这类 IO 密集型阶段,不启用就完全不可见 - 5.7+ 版本中,
setup_instruments里约 1/3 的stage/*条目默认DISABLED,不能靠“默认开”侥幸
如何关联 SQL 语句与它的执行阶段?
阶段事件不是孤立存在的,必须通过 NESTING_EVENT_ID 回溯到父语句事件。直接 JOIN events_statements_history 和 events_stages_history 是错的 —— 它们按线程和时间分别存储,没有外键字段:
- 先查语句:
SELECT THREAD_ID, EVENT_ID, SQL_TEXT FROM performance_schema.events_statements_history WHERE SQL_TEXT LIKE '%ORDER BY created_at%' - 再用返回的
EVENT_ID查阶段:SELECT EVENT_NAME, TIMER_WAIT/1e9 AS sec, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_history WHERE NESTING_EVENT_ID = 12345 AND THREAD_ID = 42 -
WORK_COMPLETED对排序阶段表示已处理行数,对文件读取表示字节数;WORK_ESTIMATED是预估总量,可用于判断是否发生磁盘临时表
IO 和内存消耗藏在哪几张表里?
阶段事件本身不记录物理 IO 或内存分配,真正暴露底层资源的是 events_waits_history 和 memory_summary_by_thread_by_event_name:
- 等待事件:查
events_waits_history中event_name以wait/io/file/或wait/synch/mutex/innodb/开头的记录,对应文件读写、缓冲池争用 - 内存使用:查
memory_summary_by_thread_by_event_name,重点关注memory/sql/JOIN_CACHE、memory/innodb/buffer_pool、memory/sql/Sort_buffer的CURRENT_NUMBER_OF_BYTES_USED - 注意:内存汇总表默认关闭,需执行
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'global_instrumentation';并重启连接才生效
实际分析时最容易被忽略的点
阶段耗时和等待事件不是线性叠加的 —— 比如 stage/sql/Sending data 耗时 2s,但期间可能穿插了 3 次 wait/io/file/innodb/innodb_data_file,每次 100ms,这些等待不会计入阶段 TIMER_WAIT,只出现在 waits 表里。想还原真实瓶颈,必须把 statements → stages → waits → memory 四层数据在同一个 THREAD_ID 下对齐时间窗口,不能只看单张表的 top 10。











