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

1次阅读

需先聚合慢日志并聚焦rows_examined远大于rows_sent的语句,再结合explain format=json、performance_schema及真实流量验证索引效果。

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

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

慢查询日志本身不告诉你“该加什么索引”,只暴露“哪条语句慢”。关键在过滤和归因:先用 mysqldumpslowpt-query-digest 聚合,重点关注 Rows_examined 远大于 Rows_sent 的语句——这通常意味着全表扫描或索引失效。

  • 避免只看 Query_time 排序:缓存命中、瞬时 IO 峰值可能干扰判断
  • 检查 EXPLAIN 时必须带上 format=JSON,关注 key 是否为 NULLtype 是否是 ALLindex
  • 注意 using filesortUsing 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=ONROW_FORMAT=DYNAMIC 下可到 3072 字节)

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

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

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

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

单靠 slow_log 只能看到“SQL 慢”,但不知道是锁等待、磁盘 IO 还是 CPU 密集。这时候要查 performance_schema.events_statements_history_longevents_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 是否下降一个数量级。

text=ZqhQzanResources