mysql索引列的顺序如何确定_mysql索引优化技巧

1次阅读

mysql联合索引需按最左前缀原则设计,等值字段前置、范围字段后置,order by/group by字段须紧接where等值条件后;函数或表达式会导致索引失效,应优化写法或用生成列。

mysql索引列的顺序如何确定_mysql索引优化技巧

WHERE 条件中字段的出现顺序决定索引列顺序

MySQL 的 B+ 树索引是按定义顺序逐列比较的,WHERE a = 1 AND b = 2 AND c > 3 这类查询,只有把 a 放在索引最左,才能用上整个索引。如果索引是 (b, a, c),那 a 就无法走最左前缀,只能用到 b 那一列(前提是 b 有等值条件)。

实操建议:

  • 把等值查询(=IN)字段放前面,范围查询(>BETWEENLIKE 'abc%')放后面
  • 如果多个字段都是等值查询,把区分度高(基数大)的字段放更左,比如 user_idstatus 更适合作为第一列
  • 避免把经常单独查的低频字段放在最左,否则其他组合查询可能用不上这个索引

ORDER BY 和 GROUP BY 字段必须紧接在 WHERE 等值条件之后

MySQL 只有在索引能“覆盖”排序或分组时,才避免额外的 filesort 或 temporary table。例如 select * FROM t WHERE a = 1 ORDER BY b, c,索引 (a, b, c) 可以复用;但若写成 (a, c, b)b 不在连续位置,就无法利用索引排序。

常见错误现象:

  • EXPLAIN 结果中 Extra 列出现 using filesort,说明排序没走索引
  • GROUP BY 后字段顺序和索引不一致,哪怕所有字段都在索引里,也可能触发临时表
  • 混合 ASC/DESC(如 ORDER BY b ASC, c DESC)在 MySQL 8.0 之前无法用索引排序,8.0+ 要求索引定义也显式声明方向

联合索引不是“字段集合”,重复建单列索引往往没用

有联合索引 (a, b, c),它天然包含 (a)(a, b) 的能力,但不包含 (b)(c) 单独查询的能力。此时再单独建 INDEX(b),不是补充,而是冗余——除非你真有高频的 WHERE b = ? 查询且无法改写 SQL。

性能与维护影响:

  • 每个索引都增加写开销(INSERT/UPDATE/delete 都要更新索引树)
  • 索引占用磁盘和内存,过多索引会拖慢 buffer pool 命中率
  • SHOW INDEX FROM table_name 查看 Cardinality,长期为 0 或极低的索引值得删掉

WHERE 中用了函数或表达式,索引直接失效

WHERE YEAR(create_time) = 2023WHERE phone LIKE '%138%'(左侧通配),MySQL 无法用索引定位,因为索引存的是原始值,不是计算结果。

可选替代方案:

  • 把函数移到右边:create_time >= '2023-01-01' AND create_time
  • 对固定前缀模糊查,用 LIKE '138%',它能走索引;但 LIKE '%138'LIKE '%138%' 不行
  • 实在要函数查询,考虑生成列(generated column)+ 函数索引(MySQL 5.7+):ALTER TABLE t ADD COLUMN y int AS (YEAR(create_time)) STORED, ADD INDEX idx_y(y)

真正容易被忽略的是:索引优化不能只看单条 SQL,得看整体查询模式。一个 (a, b, c) 索引可能让三条不同 WHERE 条件的查询受益,也可能因其中一条查 c 单独出现而完全浪费。上线前用 pt-query-digest 或 slow log 统计真实查询分布,比凭经验猜更可靠。

text=ZqhQzanResources