MySQL联合索引的原理

面试中被问到了联合索引,突然就涉及到了知识盲区,对不起,我只知道B+树,B树,哈希索引,聚簇索引,非聚簇索引,联合索引的原理?。。

对不起涉及到了我的知识盲区了。

这涉及到了我的知识盲区 憨憨猫表情包_盲区_知识_涉及表情

 

这里对联合索引做一个总结,联合索引,顾名思义,普通的索引我们只会对单个字段去构建索引,又分为主键索引和辅助索引,那么联合索引就是对多个字段去构建索引,

从而在某些场景下提升提升查询效率。

 

最左匹配原则

  提到联合索引,不得不提的就是最左匹配原则

  所谓最左原则指的就是如果你的 SQL 语句中用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配,值得注意的是,当遇到范围查询(>、<、between、like)就会停止匹配。

 

假设,我们对(a,b)字段建立一个索引,也就是说,你where后条件为

a = 1
a = 1 and b = 2

是可以匹配索引的,因为他们都遵循了最左匹配原则。但是要注意的是~你执行

b= 2 and a =1

也是能匹配到索引的,有的小伙伴就会有疑问了,这里没有遵循最左匹配原则呀,不用担心,MySQL内部有一个优化器,Mysql的优化器会自动调整a,b的顺序与索引顺序一致。 相反的,你执行

b = 2

就匹配不到索引了。 而你对(a,b,c,d)建立索引,where后条件为

a = 1 and b = 2 and c > 3 and d = 4

那么,a,b,c三个字段能用到索引,而d就匹配不到。因为遇到了范围查询,当遇到范围查询(>、<、between、like)就会停止匹配。!

 

联合索引的原理和数据结构

OK,知道了联合索引的最左匹配原则,那它的数据结构和原理是什么样子的呢。

其实它的结构和普通索引一样,还是B+树,但是细节上还是有些不一致的。

虽然依然是B+树,但联合索引的健值数量不是一个,而是多个。构建一颗B+树只能根据一个值来构建,因此数据库依据联合索引最左的字段来构建B+树。

这里引用一些大神们的图

 

preview

如图所示他们是按照a来进行排序,在a相等的情况下,才按b来排序。

因此,我们可以看到a是有序的1,1,2,2,3,3。而b是一种全局无序,局部相对有序状态! 什么意思呢?

从全局来看,b的值为1,2,1,4,1,2,是无序的,因此直接执行b = 2这种查询条件没有办法利用索引。

从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。 因此,你执行a = 1 and b = 2是a,b字段能用到索引的。而你执行a > 1 and b = 2时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。

综上所示,最左匹配原则,在遇到范围查询的时候,就会停止匹配。

所以根据联合索引的最左匹配原则,我们在构建联合索引的时候,要把区分度高的字段,放在最左侧。

 

 

 

 

 

 

 

 

 

 

 

 

 

### MySQL 联合索引的数据结构 在 MySQL 中,联合索引(composite index)是一种特殊的 B-Tree 结构[^1]。这种数据结构允许在一个索引中包含多个列,从而优化涉及多列查询的性能。 #### 创建联合索引的方式 当创建一个联合索引时,MySQL 使用指定的一组列为键值来构建一棵 B-Tree。例如: ```sql CREATE INDEX idx_composite ON table_name (column1, column2); ``` 在这个例子中,`idx_composite` 是基于 `column1` 和 `column2` 的组合而建立的一个复合索引。 #### 数据存储方式 对于每一个记录,在联合索引中的条目会按照定义顺序依次排列。具体来说,先按第一个列排序;如果有相同的值,则继续比较第二个列,依此类推直到所有的列都已参与排序为止。这样的机制使得某些类型的查询能够更高效地定位到目标行位置[^2]。 #### 查询效率提升原理 通过合理利用联合索引,可以显著减少全表扫描的机会并加快检索速度。特别是当 SQL 语句中有多个条件并且这些条件正好对应于同一个联合索引内的不同列时效果尤为明显。 #### 实际应用案例分析 假设有一个名为 `orders` 的订单表,其中包含了客户编号 (`customer_id`) 及下单日期 (`order_date`) 这两列信息。为了加速查找特定时间段内某位客户的全部订单操作,可以在上述两个字段上共同设置一个联合索引: ```sql ALTER TABLE orders ADD INDEX customer_order_idx(customer_id, order_date); ``` 这样做的好处在于:一方面可以通过快速访问某个顾客的所有历史订单;另一方面也可以方便统计每日/每月销售情况等业务需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值