mysql慢查询日志如何辅助索引优化_mysql性能诊断实战

来源:这里教程网 时间:2026-02-28 20:50:16 作者:

如何从 slow_log 找出真正需要优化的 SQL

慢查询日志本身不告诉你“该加什么索引”,只暴露“哪条语句慢”。关键在过滤和归因:先用

mysqldumpslow
pt-query-digest
聚合,重点关注
Rows_examined
远大于
Rows_sent
的语句——这通常意味着全表扫描或索引失效。

避免只看
Query_time
排序:缓存命中、瞬时 IO 峰值可能干扰判断
检查
EXPLAIN
时必须带上
FORMAT=JSON
,关注
key
是否为
NULL
type
是否是
ALL
index
注意
Using filesort
Using temporary
:即使走了索引,排序/分组没走索引也会拖慢

ALTER TABLE ADD INDEX 的三个危险操作

线上加索引不是“加完就快”,MySQL 5.6+ 虽支持

ALGORITHM=INPLACE
,但仍有隐性阻塞和空间风险。

对大表执行
ADD INDEX
前,务必确认
innodb_online_alter_log_max_size
足够(默认 128MB),否则会触发临时文件写满失败
复合索引字段顺序不能拍脑袋:WHERE 条件中等值查询字段必须前置,范围查询(
>
BETWEEN
)字段只能放在最后,否则后续字段无法命中
避免在
TEXT
/
VARCHAR(2000)
列上直接建全文索引以外的索引——InnoDB 会截断前 767 字节(
innodb_large_prefix=ON
ROW_FORMAT=DYNAMIC
下可到 3072 字节)

为什么 EXPLAIN 显示 key != NULL,但 still 慢

索引被选中不等于高效利用。常见原因包括数据分布倾斜、统计信息过期、隐式类型转换。

执行
ANALYZE TABLE
强制更新统计信息,尤其在大批量 INSERT/DELETE 后
检查 WHERE 条件是否触发隐式转换:比如
user_id
INT
,但传入字符串
'123'
,会导致索引失效
SELECT COUNT(*) FROM t WHERE indexed_col = ?
验证选择性:如果返回行数占全表 20% 以上,优化器大概率放弃走索引

慢日志 + performance_schema 联动定位真实瓶颈

单靠 slow_log 只能看到“SQL 慢”,但不知道是锁等待、磁盘 IO 还是 CPU 密集。这时候要查

performance_schema.events_statements_history_long
events_waits_history_long

开启必要消费者:
UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_%_history%';
关联查出某慢 SQL 的等待事件:
SELECT EVENT_NAME, SOURCE, TIMER_WAIT FROM performance_schema.events_waits_history_long WHERE THREAD_ID IN (SELECT THREAD_ID FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%your_slow_sql%');
若发现大量
wait/io/file/innodb/innodb_data_file
,说明是磁盘读取瓶颈;若为
wait/synch/mutex/innodb/%
,可能是并发更新冲突
实际调优中最容易被跳过的一步,是验证索引生效后的执行计划是否真的变了——别只信
EXPLAIN
输出,要在生产流量低峰期用
SELECT ... FOR UPDATE
或真实业务参数重放一次,观察
Rows_examined
是否下降一个数量级。

相关推荐