关于MySQL索引的最左前缀匹配原则原理说明说明

本文通过实例详细解析了多列索引的工作原理,包括索引的构建方式、查询过程及为何某些条件无法利用索引等问题。

假设有2个这样的SQL

SELECT * FROM table WHERE a = 1 AND c = 3; // c不走索引

SELECT * FROM table WHERE a = 1 AND b < 2 AND c = 3; // c不走索引

假设数据 表T (a,b,c) rowid 为物理位置
rowid a b c
(1) 1 1 1
(2) 2 1 13
(3) 2 2 14
(4) 1 3 3
(5) 2 3 12
(6) 1 2 5
(7) 2 3 9
(8) 1 2 2
(9) 1 3 6
(10) 2 2 11
(11) 2 2 8
(12) 1 1 7
(13) 2 3 15
(14) 1 1 4
(15) 2 1 10

当你创建一个索引 create index xxx on t(a,b), 则索引文件逻辑上等同于如下
a b rowid
1 1 1
1 1 12
1 1 14
1 2 6
1 2 8
1 3 4
1 3 9
2 1 2
2 1 15
2 2 3
2 2 10
2 2 11
2 3 5
2 3 7
2 3 13

当select * from T where a=1 and b=3 的时候, 数据库系统可以直接从索引文件中直接二分法找到A=1的记录,然后再B=3的记录。
但如果你 where b=3 则需要遍历这个索引表的全部!

多列索引是先按照第一列进行排序,然后在第一列排好序的基础上再对第二列排序,如果没有第一列的话,直接访问第二列,那第二列肯定是无序的,直接访问后面的列就用不到索引了。

你可以认为联合索引是闯关游戏的设计

例如你这个联合索引是state/city/zipCode

那么state就是第一关 city是第二关, zipCode就是第三关

你必须匹配了第一关,才能匹配第二关,匹配了第一关和第二关,才能匹配第三关

你不能直接到第二关的

索引的格式就是第一层是state,第二层才是city


如果你单独为abc建立索引的话,(a,b,c)的意思就是先找a,然后在剩下的东西里面找b,然后在剩下的东西里面找c(当然你可以不这么实现但是他们是等价的)。这个时候b和c的索引起不到任何帮助。

转载于:https://www.cnblogs.com/chenhaoyu/p/8796430.html

### MySQL 索引最左前缀匹配原则 #### 定义与原理 最左前缀匹配原则是指在使用联合索引时,查询条件必须从联合索引的第一个字段开始,并且可以连续地包含后续字段。这意味着如果有一个联合索引 `(a, b, c)`,那么有效的查询模式包括 `WHERE a = ?` 或者 `WHERE a = ? AND b = ?` 或者 `WHERE a = ? AND b = ? AND c = ?`。 当遇到范围操作符(如 `<`, `>`, `<=`, `>=`, `BETWEEN`, `LIKE &#39;prefix%&#39;`)时,最左前缀匹配会在此处终止[^2]。例如对于联合索引 `(a, b, c)`: - 查询 `WHERE a = 10 AND b > 5` 可以利用索引; - 而查询 `WHERE b = 5` 则无法有效利用此联合索引,因为缺少了最左侧的列 `a` 的过滤条件; #### 实际应用案例分析 考虑如下表结构及数据分布情况下的SQL语句执行计划解析: 假设存在一张名为 `employees` 的员工信息表格,其中定义了一个复合索引 `idx_composite(department_id, last_name)`: ```sql CREATE INDEX idx_composite ON employees (department_id, last_name); ``` 现在有两条不同的查询请求: ##### 请求一:完全符合最左前缀规则的情况 ```sql SELECT * FROM employees JOIN departments d ON e.department_id = d.id WHERE e.department_id = 1 AND e.last_name = &#39;Johnson&#39;; ``` 这条语句能够充分利用到上述创建好的联合索引 `idx_composite` 来加速查找过程,因为它严格按照了最左前缀原则提供了完整的键值组合用于筛选记录集[^1]。 ##### 请求二:部分满足最左前缀规则的情形 ```sql SELECT * FROM employees JOIN departments d ON e.department_id = d.id WHERE e.department_id = 1; ``` 即使这里只给出了联合索引中的第一个字段作为过滤条件,仍然可以在一定程度上提高检索效率,不过相比于提供全部索引字段来说性能提升可能有限。 ##### 请求三:违反最左前缀规则的例子 ```sql SELECT * FROM employees JOIN departments d ON e.department_id = d.id WHERE e.last_name = &#39;Smith&#39;; ``` 在这种情况下,由于缺失了联合索引里的首个字段 (`department_id`) ,因此整个查询将不得不绕过现有的索引来完成工作,这通常意味着更慢的速度和更高的资源消耗[^3]。 #### 性能优化建议 为了确保数据库系统的高效运行并减少不必要的I/O开销,在设计应用程序逻辑时应尽可能遵循最左前缀匹配原则来构建合适的查询表达式。同时也要注意合理规划表之间的关联关系及其对应的索引策略,从而达到最佳的整体表现效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值