MySQL 慢查询与索引排查优化

从开启慢查询日志开始,定位拖慢业务的 SQL,讲解 EXPLAIN 执行计划的读法、索引失效的常见场景以及联合索引设计原则,附可直接执行的排查与验证步骤。

先确认是不是数据库的问题

接口慢不一定是数据库。先用 top、iostat、sar 看 CPU、磁盘 IO 与负载,再看数据库连接数是否打满。如果 CPU 低、IO 低但请求仍在排队,通常是锁等待或连接池耗尽。只有确认瓶颈在数据库,再进入下面的排查流程。

开启慢查询日志

设置 slow_query_log=ON、long_query_time=0.5-1 秒、log_output=FILE。跑业务一段时间后用 mysqldumpslow 或 pt-query-digest 汇总,按「总耗时」排序而不是「单次最慢」——被调用上万次、每次 80 毫秒的 SQL 往往比偶尔一次的慢查询伤害更大。

读懂 EXPLAIN

对目标 SQL 前面加 EXPLAIN 执行,重点看这几列:

  • type:const/ref 为佳,range 可接受,index/ALL 说明走了全表扫描
  • key:实际使用的索引,NULL 表示没用上索引
  • rows:预估扫描行数,数量级越小越好
  • Extra:Using filesort 或 Using temporary 出现时要警惕

索引失效的常见场景

即便字段上有索引,写法不对依然会失效:对索引列使用函数或做运算、隐式类型转换(字符串列与数字比较)、前导模糊匹配 LIKE 后接百分号开头的模式、联合索引未满足最左前缀、用了 OR 且非索引列、选区分度过低的字段(如性别、状态)。这些场景下优化器会放弃索引,改为全表扫描。

联合索引设计

按「等值查询列在前、范围查询列在后」的顺序建立,把区分度高的字段放前面。覆盖索引能让查询直接从索引取数、避免回表,是常见提速手段。但索引不是越多越好:每个索引都会增加写入成本并占用空间,一张表上过多索引会让插入更新明显变慢。加索引前先确认这条查询确实高频且有优化空间。

验证与回归

优化后必须用同样的数据量与并发重新压测,确认耗时下降且没有引入新问题。用 EXPLAIN 再跑一遍确认执行计划符合预期。上线时选择业务低峰,必要时分批灰度。索引调整在线上大表上可能触发长时间锁表,先在从库或备份库演练一遍。

常见误区

  • 见慢就加索引,忽略了问题在 N+1 查询或分页过深
  • 深分页 LIMIT 1000000, 20,应改用基于主键位置的游标翻页
  • 一次查询返回过多列或过多行,应改为分页与字段裁剪
  • 事务持有时间过长导致锁等待,应缩短事务边界

数据库优化讲证据:先测量、再改、再验证。没有执行计划与耗时对比的优化,只能算猜测。

Previous Article

Linux 服务器磁盘空间清理实操

Next Article

crontab 定时任务实战与排错

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *