mysql索引设计错误会有什么影响_mysql性能问题分析

1次阅读

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

mysql索引设计错误会有什么影响_mysql性能问题分析

索引字段顺序错误导致查询完全走不到索引

mysql 的联合索引遵循最左前缀原则,WHERE 条件没用上索引最左边的列,后续列基本无效。比如建了 INDEX (a, b, c),但查询写成 WHERE b = 1 AND c = 2,这个索引就无法使用。

实操建议:

  • 把高频过滤、高区分度的字段放在联合索引最左侧
  • EXPLAINkeypossible_keys 是否命中预期索引
  • 注意 ORDER BYGROUP BY 字段是否能被同一索引覆盖,否则可能触发 filesort

在低区分度字段上建索引反而拖慢写入

比如对只有 ‘Y’/’N’ 两个值的 is_deleted 字段单独建索引,MySQL 查询时仍大概率走全表扫描(优化器认为索引选择性太差),而每次 INSERT/UPDATE 都要维护额外 B+ 树节点,写性能下降明显。

实操建议:

  • select count(DISTINCT col) / COUNT(*) FROM table 粗略估算选择性,低于 0.01 就谨慎建单列索引
  • 低区分度字段可考虑和高区分度字段组合成联合索引,让整体选择性提升
  • 避免对 enumTINYINT 类型且取值极少的字段单独建索引

索引过多引发 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 BYGROUP BY,需要排序聚合时得另作权衡

索引不是越多越好,也不是越长越准。真正影响性能的,往往是那个本该存在却缺失的索引,或者那个一直没人查、却每天被更新几十万次的冗余索引。

text=ZqhQzanResources