能直接定位到哪条sql在吃内存、卡cpu、扫千万行:需启用performance_schema内存与语句监控,通过memory_summary_by_digest查内存top sql、events_statements_summary_by_digest查扫描行数和执行频次top sql,并关联data_lock_waits与events_statements_current定位锁阻塞源头,结合直方图与format=tree执行计划验证优化效果。

能直接定位到哪条 SQL 在吃内存、卡 CPU、扫千万行,不用猜,也不用等慢查询日志堆积。
开启 performance_schema 内存与执行监控
MySQL 8.0 默认启用 performance_schema,但关键监控项默认是关的。不手动打开,memory_summary_global_by_event_name 这类表就是空的。
- 确认基础开关已开:
SHOW VARIABLES LIKE 'performance_schema';返回ON - 启用内存事件采集:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%'; - 启用语句级时间统计:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_statements_current', 'events_statements_history_long'); - 注意:这些操作只影响新连接,已有连接不会自动生效
查“最耗资源”的 SQL(不只是慢)
别只盯着 slow_query_log。很多问题 SQL 执行时间不到 1 秒,但每秒跑几百次、扫描上万行、反复分配内存——这才是压垮数据库的真凶。
- 查内存占用TOP SQL:
SELECT digest_text AS query, SUM_NUMBER_OF_BYTES_ALLOC FROM performance_schema.memory_summary_by_digest ORDER BY SUM_NUMBER_OF_BYTES_ALLOC DESC LIMIT 10; - 查扫描行数最多 SQL:
SELECT digest_text AS query, SUM_ROWS_EXAMINED FROM performance_schema.events_statements_summary_by_digest ORDER BY SUM_ROWS_EXAMINED DESC LIMIT 10; - 查执行频率异常高 SQL:
SELECT digest_text AS query, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY COUNT_STAR DESC LIMIT 10; - 注意:
digest_text是归一化后的语句(参数被 ? 替换),需结合events_statements_history_long查具体参数值
关联线程与锁,定位阻塞源头
光知道 SQL 慢没用,得知道它为什么慢:是等锁?等 IO?还是自己在做全表扫描?
- 找当前正在等锁的线程:
SELECT * FROM performance_schema.data_lock_waits; - 把等待线程和阻塞线程的 SQL 关联起来:
SELECT r.sql_text AS waiting_sql, b.sql_text AS blocking_sql FROM performance_schema.data_lock_waits lw JOIN performance_schema.events_statements_current r ON lw.REQUESTING_THREAD_ID = r.THREAD_ID JOIN performance_schema.events_statements_current b ON lw.BLOCKING_THREAD_ID = b.THREAD_ID; - 配合
INFORMATION_SCHEMA.PROCESSLIST看状态:SELECT ID, USER, HOST, COMMAND, TIME, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 30; - 注意:
data_lock_waits只反映“当前”锁等待,瞬时快照,需快速抓取;长期监控建议用sys.innodb_lock_waits视图
直方图 + EXPLAIN FORMAT=TREE 验证优化效果
改完索引或 SQL 后,不能只看 EXPLAIN 的预估,得验证真实执行路径是否改变。
- 更新列统计直方图(尤其倾斜数据):
ANALYZE TABLE orders UPDATE HISTOGRAM ON user_id, status WITH 100 BUCKETS; - 用树形执行计划看真实选择:
EXPLAIN FORMAT=TREE SELECT * FROM orders WHERE user_id = 1001 AND status IN (1,2);—— 它会明确告诉你是否用了索引、是否下推了条件、是否触发了临时表 - 对比优化前后
events_statements_summary_by_digest中的SUM_TIMER_WAIT和SUM_ROWS_EXAMINED是否下降 - 注意:直方图不是万能的,对高频变化字段(如状态机流转中的
status)要定期重采样,否则统计过期会导致优化器选错路
真正难的不是查出哪条 SQL 有问题,而是判断它为什么成为热点——是业务逻辑批量拉取导致,还是索引缺失被迫走全表,抑或锁竞争引发排队。这些线索散落在 performance_schema 不同的表里,必须交叉比对才能闭环。漏掉任意一环,调优就容易变成“治标不治本”。











