MySQL 查询索引最左前缀原则,如果是(a,b)的联合索引,WHERE b = ? AND a = ?会走索引吗

从SQL原本的理解上,不会走联合索引

但是MySQL有优化器,会针对 WHERE b = ? AND a = ? 这种特定情况进行优化,使其走联合索引(a,b)

  • 优化器的版本要求 MySQL >= 5.7
  • 如果其中有唯一索引,比如a是唯一索引,这里就不会走联合索引了,会走唯一索引,这样更快

在 MySQL 中,联合索引 (a, b) 的查询顺序必须遵循"最左前缀原则" 。如果查询条件是 WHERE b = ? AND a = ?,虽然逻辑上等价于 WHERE a = ? AND b = ?,但能否利用联合索引取决于实际书写顺序和优化器的处理。以下是详细分析:


1. 联合索引 (a, b) 的存储结构

  • 索引是按照 (a, b) 的顺序存储的,即先按 a 排序,a 相同的情况下再按 b 排序。
  • 最左前缀原则:查询必须从索引的最左列开始,才能有效利用索引。

2. WHERE b = ? AND a = ? 的情况

(1) 能否利用索引?

  • 严格来说,不能直接利用 (a, b) 索引 ,因为查询条件没有从 a 开始。
  • 但 MySQL 优化器可能会自动重写条件
    • 如果优化器将 WHERE b = ? AND a = ? 重写为 WHERE a = ? AND b = ?,则可以利用索引。
    • 如果未重写,则无法利用索引,可能导致全表扫描。

(2) 实验验证

表结构与索引
复制代码

sql

复制代码
`CREATE TABLE test (
    id INT PRIMARY KEY,
    a INT,
    b INT,
    INDEX idx_a_b (a, b)
);`
查询 1:WHERE a = 1 AND b = 2(符合最左前缀)
复制代码

sql

复制代码
`EXPLAIN SELECT * FROM test WHERE a = 1 AND b = 2;`
  • 结果 :会使用 idx_a_b 索引(key: idx_a_b)。
查询 2:WHERE b = 2 AND a = 1(条件顺序相反)
复制代码

sql

复制代码
`EXPLAIN SELECT * FROM test WHERE b = 2 AND a = 1;`
  • 结果
    • MySQL 5.7+ 和 8.0 :优化器会自动重写为 WHERE a = 1 AND b = 2,仍然使用 idx_a_b
    • 旧版本 MySQL:可能无法利用索引,导致全表扫描。

3. 关键结论

  1. 索引顺序是物理存储顺序,查询必须从最左列开始才能高效利用。
  2. MySQL 优化器会尝试重写条件 ,因此 WHERE b = ? AND a = ? 在大多数现代版本中仍能利用 (a, b) 索引。
  3. 但依赖优化器不可靠 ,建议显式写成 WHERE a = ? AND b = ? 以确保索引被使用。

4. 其他相关场景

(1) 只查询 b 列(WHERE b = ?

  • 无法利用 (a, b) 索引 ,因为缺少 a 的条件。
  • 解决方法:
    • 单独为 b 创建索引。
    • 使用覆盖索引(如 (b, a))。

(2) 范围查询 + 精确匹配

  • WHERE a = 1 AND b > 10:可以利用 (a, b) 索引(先定位 a = 1,再在范围内找 b > 10)。
  • WHERE a > 1 AND b = 10只能用到 a 的部分索引 ,因为 b 的条件在范围查询后无法高效过滤。

5. 最佳实践

  1. 遵循最左前缀原则:查询条件从索引的最左列开始。
  2. 显式书写条件顺序 :避免依赖优化器重写,直接写 WHERE a = ? AND b = ?
  3. 使用 EXPLAIN 验证:检查执行计划是否真的用了索引。
  4. 考虑索引覆盖 :如果只需查询 ab,确保索引包含所有需要的列(如 INDEX idx_a_b (a, b))。

总结

  • WHERE b = ? AND a = ? 在现代 MySQL 中通常能利用 (a, b) 索引(因优化器重写)。
  • 但最安全的方式是显式写成 WHERE a = ? AND b = ?
  • 如果查询不符合最左前缀(如仅 WHERE b = ?),则无法利用 (a, b) 索引

建议通过 EXPLAIN 实际验证查询计划!

相关推荐
oradh2 小时前
Oracle TX 锁 Mode 4(Share)问题排查总结
数据库·oracle·tx 锁 mode 4·oracle tx 锁
2601_962065253 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql
yi.Ist3 小时前
数据定义语言-DDL操作
数据库·学习·mysql·oracle·大海豚
阿kun要赚马内3 小时前
MySQL 索引基础
后端·mysql
2601_963282774 小时前
工程项目、政企采购为什么优先选择对讲机批量采购?
数据库
Doraemomo4 小时前
SQLite数据库
数据库·sqlite
2601_962177135 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql
云贝教育-郑老师5 小时前
MySQL 的“黑匣子“:Performance Schema 把数据库内部变成一张可查的表
数据库·mysql
这个DBA有点耶7 小时前
同城双活落地的三座山:网络延迟、脑裂预防、反向同步
数据库·架构·dba