慢查询指执行时间超过long_query_time阈值的SQL语句,包含锁等待、IO等全部耗时;其日志是实时性能探针,需配合工具分析模式而非单条语句,且应按需开启避免性能损耗。

慢查询就是执行时间超阈值的SQL语句
在MySQL里,“慢查询”不是主观判断,而是有明确数字标准的:只要一条SQL的执行时间超过long_query_time设定的秒数,它就算慢查询。默认值是10秒,但生产环境普遍设为1秒甚至0.5秒——因为用户等不到10秒,电商页面加载超2秒,转化率就开始掉。
注意,这个“执行时间”包含锁等待、磁盘IO、排序、临时表创建等全部环节,不只是CPU计算时间。所以一条看似简单的SELECT * FROM orders WHERE user_id = ?,如果user_id没索引、表有千万行,就很可能卡住几秒,被记入慢日志。
慢查询日志不是“备查档案”,而是实时性能探针
它的核心作用不是事后追责,而是暴露系统真实负载压力点:
-
slow_query_log开启后,每条超时SQL会记录完整语句(含实际参数)、耗时、扫描行数Rows_examined、线程ID、客户端IP——这些信息直接对应EXPLAIN里的关键指标 - 配合
log_queries_not_using_indexes = ON,还能揪出“语法正确但没走索引”的隐形杀手,比如WHERE status + 0 = 1这种隐式类型转换 - 日志本身可输出到文件(
log_output = FILE)或系统表mysql.slow_log,后者方便用SQL聚合分析,但写表有额外开销,高并发下慎用
临时开启和永久配置的关键区别
开发调试时常用动态命令快速验证:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1; SET GLOBAL log_output = 'FILE';
但这些设置在MySQL重启后失效,且仅对新连接生效——已存在的连接不会突然开始记慢日志。真正上线必须改配置文件/etc/my.cnf,在[mysqld]段加上:
slow_query_log = ON slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 0.5 log_queries_not_using_indexes = OFF # 非调优期别开,日志量爆炸
容易踩的坑:long_query_time支持小数(如0.5),但单位始终是秒;另外,SET GLOBAL修改后,需确认SHOW VARIABLES LIKE 'long_query_time'返回的是新值——某些旧版本MySQL存在缓存延迟。
不分析日志,开启等于白开
一天几GB的原始日志根本没法人工翻。必须用工具提炼重点:
-
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log:按总耗时排序,取前10条最耗时的模板(自动忽略参数差异) -
pt-query-digest /var/log/mysql/mysql-slow.log --limit 5(Percona Toolkit):输出更细粒度统计,包括95%响应时间、平均扫描行数、索引使用率等
真正要盯住的不是“哪条SQL最慢”,而是“哪类模式反复出现”:比如大量LIMIT 10000,20分页、LIKE '%keyword%'全表扫、或同一张表被高频SELECT ... FOR UPDATE阻塞。这些才是优化的靶心。
最后提醒一句:慢查询日志本身有性能损耗,尤其是高QPS场景下,频繁写磁盘会影响吞吐。所以它不该常驻开启,而应作为“诊断开关”——问题浮现时打开,定位后关闭,优化上线再验证。长期开着却不分析,反而掩盖了更深层的问题。










