MySQL 慢查询定位与索引优化的实战记录
订单表数据量过了千万级后,后台的一个统计查询开始明显变慢,最严重时耗时 3.2s。记录一下整个定位和优化的过程。
定位慢查询
先确认慢查询日志已开启:
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
抓到慢 SQL 后,用 EXPLAIN 看执行计划:
EXPLAIN SELECT ... FROM orders
WHERE user_id = 12345 AND status = 2
ORDER BY created_at DESC LIMIT 20;
发现问题
EXPLAIN 结果显示 type=ALL,走了全表扫描,rows 上千万。原来这条查询从来没用上索引。
建立联合索引
ALTER TABLE orders
ADD INDEX idx_user_status_created (user_id, status, created_at);
联合索引的列顺序很关键,要遵循「最左前缀」原则:等值条件放前面,范围/排序条件放后面。
进阶:覆盖索引
如果查询只用到了索引里的列,MySQL 就能直接从索引返回结果,不用回表:
ALTER TABLE orders
ADD INDEX idx_cover (user_id, status, created_at, amount);
这样 Extra 会显示 Using index,性能再上一个台阶。
结果
优化后该查询耗时从 3.2s 降到 80ms。更重要的是,CPU 负载也降下来了,因为不再有大量的全表扫描。
小结
索引优化的核心就三件事:看懂 EXPLAIN、遵循最左前缀、能用覆盖索引就用覆盖索引。