索引字段顺序错误导致查询完全走不到索引
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,需要排序聚合时得另作权衡 索引不是越多越好,也不是越长越准。真正影响性能的,往往是那个本该存在却缺失的索引,或者那个一直没人查、却每天被更新几十万次的冗余索引。
