开启 log_queries_not_using_indexes 能记录未用索引的查询,但必须先启用 slow_query_log = ON,否则无效;其触发依赖优化器实际判定弃用索引,且易因 min_examined_row_limit、long_query_time 或日志路径权限等问题导致无记录。

直接说结论:开启 log_queries_not_using_indexes 能记录所有未走索引的查询,但必须配合 slow_query_log = ON 才生效,且极易产生海量日志——尤其在低数据量表或 WHERE 条件无法命中索引时。
为什么 set global log_queries_not_using_indexes = ON 没反应?
这个变量本身不独立工作。MySQL 只有在慢查询日志已启用的前提下,才会把“未用索引”的查询也写进 slow_query_log_file。如果 slow_query_log 是 OFF,哪怕你开了 log_queries_not_using_indexes,也不会生成任何日志。
验证方式很简单:
- 先执行
SHOW VARIABLES LIKE 'slow_query_log';—— 必须是ON - 再查
SHOW VARIABLES LIKE 'log_queries_not_using_indexes';—— 确认是ON - 最后执行一条明确不走索引的 SQL(比如对无索引字段
SELECT * FROM t WHERE name = 'x'),看日志文件是否有新增条目
log_queries_not_using_indexes 的真实触发条件
它不是“只要没建索引就记”,而是 MySQL 优化器实际执行时判定“本次查询放弃使用索引”。常见触发场景包括:
- 字段有索引,但
WHERE中用了函数或类型隐式转换(如WHERE DATE(create_time) = '2026-05-01') - 索引列参与了运算(如
WHERE id + 1 = 100) - 数据量极小(比如表只有几十行),优化器认为全表扫描比走索引更快
- 使用了
OR且部分分支无法用索引,导致整个条件退化 - 复合索引最左前缀未被满足(如索引是
(a,b,c),却只查WHERE b = 1)
注意:EXPLAIN 输出中 key 为 NULL、type 为 ALL 或 index,基本就对应会被该日志捕获。
配置时最容易踩的三个坑
很多人开了这个选项后发现日志爆炸,或者压根没记录,问题往往出在这儿:
-
long_query_time设得太高(比如默认 10 秒),而未用索引的查询可能只耗时 0.02 秒——它不会被记入慢日志,自然也不会被log_queries_not_using_indexes捕获。建议临时调成0或0.1做测试(生产慎用) - 配置写进了
[client]或[mysql]段,而不是[mysqld]段,导致服务端根本没读到 - 日志路径目录权限不对,MySQL 进程无法写入
slow_query_log_file,结果所有日志(包括未用索引的)都静默丢失
要不要在生产环境长期开启?
一般不建议。它对诊断索引缺失问题很有用,但代价明显:
- 即使一条简单
SELECT * FROM user WHERE status = 0,只要status没索引,就会被记;高频小表很容易撑爆磁盘 - 日志内容和普通慢查询一样,但缺乏
Query_time对比,难判断“是真慢”还是“只是没走索引但其实很快” - 真正该做的是定期用
pt-query-digest分析慢日志 +EXPLAIN复查高频查询,而不是靠这个开关兜底
更务实的做法:上线新功能前临时打开几小时,抓出漏建索引的语句;或在低峰期对关键表做专项扫描,之后立刻关掉。


















