MySQL 索引优化实战:从 Explain 分析到查询性能翻倍
时间:2026-10-4 09:52 作者:emer 分类: 无
前言
数据库查询慢是 Web 开发中最常见的性能问题之一。而绝大多数慢查询都可以通过合理使用索引来解决。本文将从 Explain 执行计划入手,带你一步步掌握 MySQL 索引优化的实战技巧。
一、认识 Explain 执行计划
要优化查询,首先得知道 MySQL 是怎么执行你的 SQL 的。EXPLAIN 命令可以展示 MySQL 执行查询的详细步骤:
EXPLAIN SELECT * FROM orders WHERE user_id = 10086 AND status = 'paid';
重点关注以下几个字段:
- type:访问类型,从好到差依次为
const > eq_ref > ref > range > index > ALL。出现ALL就是全表扫描,必须优化。 - key:实际使用的索引。如果为 NULL,说明没有用到索引。
- rows:预估需要扫描的行数。这个值越大越慢。
- Extra:额外信息。
Using filesort和Using temporary都是危险信号。
二、最左前缀原则
联合索引 (a, b, c) 的匹配规则:
-- 用到索引 a,b,c
SELECT * FROM t WHERE a = 1 AND b = 2 AND c = 3;
-- 用到索引 a,b
SELECT * FROM t WHERE a = 1 AND b = 2;
-- 只用到索引 a(中间断了)
SELECT * FROM t WHERE a = 1 AND c = 3;
-- 完全用不到索引
SELECT * FROM t WHERE b = 2 AND c = 3;
实战要点:把等值查询的列放在前面,范围查询的列放在后面。
三、常见索引失效场景
1. 对索引列使用函数或运算
-- 失效:对索引列用了函数
SELECT * FROM users WHERE DATE(created_at) = '2026-01-01';
-- 有效:改成范围查询
SELECT * FROM users WHERE created_at >= '2026-01-01' AND created_at < '2026-01-02';
2. 隐式类型转换
-- 失效:phone 是 varchar,用数字查
SELECT * FROM users WHERE phone = 13800138000;
-- 有效:加引号
SELECT * FROM users WHERE phone = '13800138000';
3. LIKE 以通配符开头
-- 失效
SELECT * FROM users WHERE name LIKE '%张%';
-- 有效
SELECT * FROM users WHERE name LIKE '张%';
四、实战优化案例
问题 SQL(扫描 10 万行,耗时 1.2 秒):
SELECT id, title, created_at FROM articles
WHERE category_id = 5 AND status = 'published'
ORDER BY created_at DESC LIMIT 20;
Explain 结果:type=index,rows=120000,Using filesort。
优化方案:创建联合索引
ALTER TABLE articles ADD INDEX idx_cat_status_time (category_id, status, created_at DESC);
优化后:type=ref,rows=20,Extra 无 filesort。查询时间从 1.2 秒降到 0.005 秒。
五、索引不是越多越好
索引虽然能加速查询,但也有代价:
- 写入变慢:每次 INSERT/UPDATE 都要维护索引
- 占用空间:索引也是要存磁盘的
- 优化器选错:索引太多可能让优化器犯迷糊
建议:单表索引数量控制在 5 个以内,避免重复索引和冗余索引。
总结
MySQL 索引优化的核心思路:
- 用
EXPLAIN看执行计划,找到慢的原因 - 遵循最左前缀原则设计联合索引
- 避免常见的索引失效写法
- 定期清理无用索引
掌握这些技巧,你就能解决 80% 以上的慢查询问题。