在 MySQL 中建立索引是优化查询性能的关键操作,但若使用不当可能导致存储开销增加、写入效率降低甚至性能反降。以下是建索引时需要重点注意的事项及对应分析:
一、索引设计原则
-
选择高选择性列
- 原理:选择性 = 不同值数量 / 总行数,值越接近1(如主键、唯一ID)越适合建索引。
- 反例:对性别(男/女)建索引,选择性仅0.5,优化效果极低,不如全表扫描。
- 建议:优先为WHERE、JOIN、ORDER BY中频繁出现的列建索引。
-
避免过度索引
- 代价:每个索引需占用存储空间(B+树结构),且写入(INSERT/UPDATE/DELETE)时需额外维护索引。
- 案例:一张10万行、10个索引的表,写入速度可能比无索引表慢3倍以上。
- 工具:通过
SHOW INDEX FROM 表名
监控索引使用频率,删除长期未使用的索引。
-
复合索引的列顺序
- 原则:遵循“最左前缀”规则,将选择性高、过滤性强的列放在左侧。
- 示例:索引
(a, b, c)
可优化a=1
、a=1 AND b=2
、a=1 AND b=2 AND c=3
,但无法优化b=2
或c=3
单独查询。 - 反例:将
(user_id, create_time)
改为(create_time, user_id)
后,按时间范围查询的效率可能大幅下降。
二、索引类型选择
-
普通索引 vs 唯一索引
- 普通索引:允许重复值,适用于频繁更新的列。
- 唯一索引:强制唯一性,适合主键或业务唯一键(如手机号),但写入时需检查重复。
-
前缀索引
- 适用场景:对长字符串(如URL、邮箱)建索引时,可截取前N个字符。
- 语法:
ALTER TABLE 表名 ADD INDEX idx_name (column_name(10))
。 - 限制:无法用于ORDER BY或GROUP BY,需权衡选择性。
-
全文索引(FULLTEXT)
- 适用场景:对文本内容(如文章、商品描述)进行模糊搜索。
- 注意:仅支持MyISAM(5.6前)和InnoDB(5.6+),且默认不支持中文分词(需使用ngram插件)。
-
空间索引(SPATIAL)
- 适用场景:地理空间数据(如Point、Polygon)的查询。
- 限制:仅支持MyISAM(5.7前)和InnoDB(5.7+),且列必须为
NOT NULL
。
三、索引使用优化
-
避免索引失效
- 常见陷阱:
- 对索引列使用函数(如
WHERE YEAR(create_time) = 2023
)或隐式转换(如字符串与数字比较)。 - 使用
NOT IN
、!=
、<>
、OR
(除非所有条件列均有索引)。 - 查询条件范围过大(如
age > 80
且数据分布不均)。
- 对索引列使用函数(如
- 解决方案:改用等值查询、拆分
OR
为UNION ALL
、调整查询逻辑。
- 常见陷阱:
-
覆盖索引(Covering Index)
- 原理:索引包含查询所需的所有列(如
SELECT a, b FROM t WHERE a=1
,索引(a, b)
),避免回表。 - 优势:减少I/O操作,提升查询速度。
- 原理:索引包含查询所需的所有列(如
-
索引下推(ICP)
- 适用场景:MySQL 5.6+对复合索引的优化,将WHERE条件过滤下推到存储引擎层。
- 示例:
SELECT * FROM t WHERE a=1 AND b>10
,索引(a, b)
下可先过滤a=1
再检查b>10
。
四、其他注意事项
-
外键与索引
- 建议:对外键列自动建索引(InnoDB默认行为),避免JOIN时全表扫描。
-
自增主键 vs 业务主键
- 自增主键:适合InnoDB(聚簇索引),写入性能高。
- 业务主键:如UUID,可能导致索引碎片化,需定期
OPTIMIZE TABLE
。
-
索引监控与维护
- 工具:
EXPLAIN
:分析查询是否使用索引。SHOW STATUS LIKE 'Handler_read%'
:监控索引读取次数。
- 定期任务:对大表重建索引(
ALTER TABLE ... ENGINE=InnoDB
)。
- 工具:
五、总结
场景 | 索引策略 | 避免操作 |
---|---|---|
高选择性列 | 建普通索引或唯一索引 | 对低选择性列建索引(如性别) |
复合查询 | 按“最左前缀”设计复合索引 | 随意调整索引列顺序 |
长字符串查询 | 建前缀索引 | 全字段索引(浪费空间) |
模糊搜索 | 建全文索引(需分词) | 用LIKE '%keyword%' (无法用索引) |
地理空间数据 | 建空间索引 | 用普通索引查询空间数据 |
核心原则:索引设计需平衡查询效率与写入开销,通过EXPLAIN
和监控工具持续优化。
我正在程序员刷题神器面试鸭上高效准备面试,9000+ 高频面试真题、800 万字优质题解,覆盖主流编程方向,跟我一起刷原题、过面试:点击进入