慢查询日志中Query_time长但手动执行快,是因实际执行时存在锁等待、Buffer Pool冷启动、临时表落盘或统计信息陈旧等环境差异;Lock_time接近Query_time表明主要耗时在等锁。

慢查询日志里记录了 Query_time 很长,但手动 EXPLAIN 或重复执行却很快
这是典型的时间差问题:慢查询日志记录的是语句在**实际执行时的完整耗时**,而你手动执行时环境已不同。常见原因包括锁等待、Buffer Pool 热度、临时表落盘、统计信息陈旧等。尤其要注意 Lock_time 字段——如果它接近 Query_time,说明语句大部分时间卡在等锁(如行锁、MDL 锁),而非执行本身。
检查慢查询日志是否启用了 log_queries_not_using_indexes 误报
该配置会让所有未走索引的查询(哪怕只查 10 行)都进慢日志,和实际性能无关。确认是否被误触发:
- 查看日志中对应条目是否有
Rows_examined极小(如 12)、Rows_sent也很小,但Query_time却 >1s - 检查 MySQL 配置:
SELECT @@log_queries_not_using_indexes;,若为ON且业务存在大量短小的全表扫描(如配置表单查),就会污染慢日志 - 临时关闭验证:
SET GLOBAL log_queries_not_using_indexes = OFF;(注意仅对新连接生效)
SHOW PROFILES 和 SHOW PROFILE FOR QUERY N 能定位真实瓶颈
慢日志只给总时间,而 SHOW PROFILE 可拆解每个阶段耗时(如 creating tmp table、Sorting result、Sending data)。前提是:SELECT @@profiling; 返回 1,且当前会话开启了 profiling(SET profiling = 1;)。
- 执行疑似慢语句后,立即运行
SHOW PROFILES;找到最新 Query_ID - 再执行
SHOW PROFILE FOR QUERY N;,重点关注Duration最大的阶段 - 若卡在
Copying to tmp table on disk,说明tmp_table_size或max_heap_table_size太小,导致内存临时表被迫落地磁盘
执行计划变化导致“偶发性慢”,重点看 table_scan 和 rows_examined
同一条 SQL 在慢日志里有时快有时慢,大概率是优化器选错了执行路径。关键看日志中的 Rows_examined 是否剧烈波动(比如平时 500,慢的时候突然跳到 80 万)。
- 用
EXPLAIN FORMAT=JSON对比快/慢时刻的执行计划,特别关注key(是否走了预期索引)、rows(预估扫描行数)、filtered(过滤率) - 检查统计信息是否过期:
ANALYZE TABLE your_table;强制更新;或调大innodb_stats_auto_recalc - 避免隐式类型转换:比如
WHERE user_id = '123'(字段是BIGINT),会导致索引失效,Rows_examined暴增
information_schema.INNODB_TRX、PROCESSLIST 和 SHOW ENGINE INNODB STATUS 交叉印证。










