如何打开慢查询日志?long_query_time、log_queries_not_using_indexes 的作用?
How to enable the slow query log? What is the function of long_query_time
考察要点
这道题面试官想看你是否掌握 MySQL 性能优化的基础工具——慢查询日志。它不仅考察你是否知道如何开启和配置,更深层次是考察你对性能问题定位的系统性方法论,以及在生产环境中权衡功能开关带来的性能开销的工程意识。
核心概念
慢查询日志(Slow Query Log)是 MySQL 提供的一种日志记录,用于记录执行时间超过指定阈值的 SQL 语句。它是 DBA 和开发人员定位性能瓶颈、优化 SQL 的首要工具。
1. 核心参数与作用
| 参数名 | 作用 | 默认值 | 说明 |
|---|---|---|---|
slow_query_log | 慢查询日志的总开关。 | OFF | 设为 ON 或 1 开启。 |
slow_query_log_file | 指定慢查询日志的文件路径和名称。 | host_name-slow.log | 路径通常在 datadir 下。 |
long_query_time | 慢查询的时间阈值,单位为秒。 | 10.000000 | 执行时间超过此值的 SQL 会被记录。支持微秒精度。生产环境通常设为 0.1 到 1 之间。 |
log_queries_not_using_indexes | 是否记录没有使用索引的查询。 | OFF | 这是一个非常强大的补充。即使查询执行很快(低于 long_query_time),只要它没有利用索引进行查找,也会被记录下来。这有助于发现潜在的性能隐患。 |
log_output | 日志的输出格式。 | FILE | - FILE: 存为普通文件,性能开销小,适合 pt-query-digest 等工具分析。<br>- TABLE: 存入 mysql.slow_log 表,方便用 SQL 查询,但有写入开销和锁争用风险。<br>- NONE: 关闭日志。 |
min_examined_row_limit | 配合 log_queries_not_using_indexes 使用,只有当查询检查的行数超过此值时,才记录该“未使用索引”的查询。 | 0 | 用于过滤掉对小表的全表扫描,减少日志噪音。例如,SELECT * FROM config 这种表本身就几行,全表扫描是最高效的,不应被视为慢查询。 |
2. 如何开启和配置
有两种方式:动态配置(服务器运行时修改)和静态配置(修改配置文件)。
动态配置(临时生效,重启后失效)
适合临时性的诊断和调试。
1-- 1. 查看当前配置2SHOW VARIABLES LIKE '%slow%';3SHOW VARIABLES LIKE 'long_query_time';45-- 2. 开启慢查询日志6SET GLOBAL slow_query_log = 'ON';78-- 3. 设置慢查询时间阈值为 0.5 秒9SET GLOBAL long_query_time = 0.5;1011-- 4. 开启“未走索引”的查询记录12SET GLOBAL log_queries_not_using_indexes = 'ON';1314-- 5. 修改日志输出到 TABLE (可选)15SET GLOBAL log_output = 'TABLE,FILE'; -- 可以同时输出到两种格式
注意:SET GLOBAL 只对新建立的连接生效。对于当前会话,可以使用 SET SESSION long_query_time = 0.5;。
静态配置(永久生效)
修改 MySQL 配置文件(Linux 通常是 /etc/my.cnf,Windows 是 my.ini),在 [mysqld] 节下添加或修改配置。
1[mysqld]2# 开启慢查询日志3slow_query_log = 145# 慢查询日志文件路径6slow_query_log_file = /var/lib/mysql/mysql-slow.log78# 慢查询时间阈值(秒)9long_query_time = 0.51011# 记录没有使用索引的查询12log_queries_not_using_indexes = 11314# 检查行数超过1000才记录未使用索引的查询15min_examined_row_limit = 1000
修改后需要重启 MySQL 服务才能生效。
常见低分回答
- 只知道
long_query_time:回答时只提long_query_time,不知道log_queries_not_using_indexes,说明对慢查询的理解只停留在“慢”,而没有意识到“不高效”也是关键问题。 long_query_time设置不合理:当被问到生产环境设为多少时,回答“默认的 10 秒就行”。这在任何一个有一定访问量的线上系统都是完全不可接受的,10 秒的查询足以拖垮整个应用。- 滥用
log_queries_not_using_indexes:不假思索地建议在所有生产环境永久开启log_queries_not_using_indexes。这会产生大量日志,在高并发下对磁盘 I/O 造成显著压力,属于没有考虑性能开销的回答。 - 混淆
GLOBAL和SESSION:在SET配置时,不清楚GLOBAL和SESSION的作用域区别,误以为SET SESSION会对所有连接生效。 - 不知道如何分析日志:只知道如何开启,但当被问到“开启后怎么用”时,回答“用
cat或less去看”,而不知道使用mysqldumpslow或pt-query-digest等专业工具进行聚合分析。
工程实践与优化
-
日志分析工具:
mysqldumpslow:MySQL 自带的工具,功能简单,主要用于对慢查询日志进行分类、汇总。pt-query-digest:Percona Toolkit 中的王牌工具,强烈推荐。它能对日志进行“指纹”分析(将id=1和id=2的同类 SQL 归为一类),并按总耗时、平均耗时、出现频率等多个维度进行排序输出,生成详尽的分析报告。这是定位核心慢 SQL 的不二之选。
bash1# 示例:分析最近一小时的慢查询,并输出报告2pt-query-digest /var/lib/mysql/mysql-slow.log > slow_query_report.txt -
性能开销与权衡:
- 开启慢查询日志(尤其是
log_output=FILE)对性能的影响通常在 1%-5% 之间,对于绝大多数系统是可以接受的。 log_queries_not_using_indexes开启时,如果系统中存在大量全表扫描操作,会导致日志文件迅速膨胀,I/O 压力增大。建议在性能诊断期间短期开启,或配合min_examined_row_limit使用。log_output=TABLE的写入开销比FILE大,因为它涉及到InnoDB的事务、锁、MVCC等机制。在高并发写入场景下,mysql.slow_log表本身可能成为瓶颈。
- 开启慢查询日志(尤其是
-
日志轮转(Log Rotation): 生产环境必须配置日志轮转,防止单个日志文件无限增长撑爆磁盘。可以通过
logrotate工具配置,或者手动执行mv重命名旧日志文件后,执行FLUSH SLOW LOGS;或mysqladmin flush-logs来让 MySQL 创建新的日志文件。 -
集中式日志平台: 在大规模分布式系统中,通常会将慢查询日志通过
filebeat等工具采集,发送到 ELK (Elasticsearch, Logstash, Kibana) 或 Loki 等集中式日志平台,进行统一的存储、查询、监控和告警。
常见追问与延伸题目
-
追问:你找到了一个慢查询,接下来你的优化步骤是什么?
- 回答要点 1 (分析):使用
EXPLAIN或EXPLAIN ANALYZE(MySQL 8.0+) 查看其执行计划。重点关注type(是否为ALL全表扫描),key(是否用上了正确的索引),rows(预估扫描行数),Extra(是否出现Using filesort,Using temporary)。 - 回答要点 2 (诊断):结合业务场景,分析 SQL 逻辑。是否存在多余的
JOIN?WHERE条件是否可索引?GROUP BY或ORDER BY的字段是否能通过索引来优化? - 回答要点 3 (优化):根据分析结果进行优化。可能是创建或修改索引(如添加联合索引,调整索引顺序),也可能是改写 SQL(如拆分复杂查询、避免在索引列上使用函数),甚至是调整表结构或业务逻辑。
- 回答要点 4 (验证):在测试环境验证优化效果,再次
EXPLAIN确认执行计划符合预期,并进行压测,确保性能提升且结果正确。
- 回答要点 1 (分析):使用
-
追问:如果
log_queries_not_using_indexes产生的日志太多,有没有更精细化的方法找到那些没有走索引的查询?- 回答要点 1 (Performance Schema):使用 Performance Schema。这是比慢查询日志更现代、更底层的性能监控工具。可以查询
events_statements_summary_by_digest表,通过SUM_NO_INDEX_USED和SUM_NO_GOOD_INDEX_USED字段来统计和排序那些全表扫描或未使用最佳索引的 SQL 类型。这种方式开销更可控,数据更结构化。 - 回答要点 2 (第三方监控):利用 Prometheus +
mysqld_exporter监控体系。mysqld_exporter会从 Performance Schema 中采集相关指标,可以通过 Grafana 仪表盘直观地监控Select_scan(全表扫描次数) 等关键指标的增长率,并设置告警。
- 回答要点 1 (Performance Schema):使用 Performance Schema。这是比慢查询日志更现代、更底层的性能监控工具。可以查询
-
追问:日志输出到
FILE和TABLE各有什么优缺点?你在什么场景下会选择哪一种?- 回答要点 1 (
FILE):- 优点:性能开销低,对数据库本身影响小;是业界标准工具(如
pt-query-digest)的默认输入源;日志独立于数据库实例,即使数据库崩溃,日志文件通常依然存在。 - 缺点:需要服务器文件系统访问权限才能查看和分析;非结构化文本,不方便直接用 SQL 查询。
- 场景:首选于所有生产环境,特别是高并发、高负载的系统。
- 优点:性能开销低,对数据库本身影响小;是业界标准工具(如
- 回答要点 2 (
TABLE):- 优点:可以直接用 SQL 查询分析,非常方便;可以远程查询,无需登录服务器;便于和其他数据库表做关联分析。
- 缺点:对数据库有写入开销,
mysql.slow_log表本身可能成为性能瓶颈;如果对slow_log表的查询本身很慢,可能会造成循环记录;表大小需要管理,否则会占用过多存储空间。 - 场景:适用于开发环境、测试环境或负载非常低的内部系统,此时便利性优先于极致性能。
- 回答要点 1 (