索引设计需遵循最左前缀原则、控制区分度、避免冗余、合理设置前缀长度;高频过滤字段置左,低区分度字段慎建单列索引,写多读少表索引数宜控制在4–5个以内。

索引字段顺序错误导致查询完全走不到索引
MySQL 的联合索引遵循最左前缀原则,WHERE 条件没用上索引最左边的列,后续列基本无效。比如建了 INDEX (a, b, c),但查询写成 WHERE b = 1 AND c = 2,这个索引就无法使用。
实操建议:
- 把高频过滤、高区分度的字段放在联合索引最左侧
- 用
EXPLAIN看key和possible_keys是否命中预期索引 - 注意
ORDER BY和GROUP BY字段是否能被同一索引覆盖,否则可能触发 filesort
在低区分度字段上建索引反而拖慢写入
比如对只有 'Y'/'N' 两个值的 is_deleted 字段单独建索引,MySQL 查询时仍大概率走全表扫描(优化器认为索引选择性太差),而每次 INSERT/UPDATE 都要维护额外 B+ 树节点,写性能下降明显。
实操建议:
- 用
SELECT COUNT(DISTINCT col) / COUNT(*) FROM table粗略估算选择性,低于 0.01 就谨慎建单列索引 - 低区分度字段可考虑和高区分度字段组合成联合索引,让整体选择性提升
- 避免对
ENUM、TINYINT类型且取值极少的字段单独建索引
索引过多引发 INSERT/UPDATE 延迟和锁竞争
每多一个索引,插入一行就要同步更新多个 B+ 树,不仅耗 CPU 和 I/O,还会延长行锁持有时间。尤其在高并发写入场景下,容易出现 lock wait timeout 或主从延迟加剧。
实操建议:
- 用
SHOW INDEX FROM table_name定期检查未被使用的索引(配合performance_schema.table_io_waits_summary_by_index_usage) - 删除长期
rows_read = 0的索引 - 写多读少的表,索引总数控制在 4–5 个以内更稳妥
字符串字段没加前缀长度就建索引
对 VARCHAR(500) 字段直接建 INDEX (content),MySQL 默认会为索引项分配全部 500 字符空间(utf8mb4 下达 2000 字节),导致索引体积暴增、内存占用高、缓存命中率下降,甚至触发 index column too long 报错。
实操建议:
- 用
SELECT MAX(LENGTH(col)) FROM table查真实最大长度,再定前缀长度 - 英文/数字类字段通常 10–20 足够;中文标题类可设 30–60,但别盲目拉满
- 前缀索引无法用于
ORDER BY和GROUP BY,需要排序聚合时得另作权衡











