联合索引的最左前缀原则属于面试高频题,想必大部分同学都知道一些,但是,那些不符合最左前缀的部分,会怎么样呢(索引下推)
索引下推不算高频题,知道的同学应该不是很多(不过并不代表有啥难度哈,挺简单的),学起来装波杯
老规矩,背诵版在文末。点击 大厂面试火箭计划 可以直达我收录整理的各大厂面试真题
引子
看下面这张用户表,包含主键 id、身份证号 id_card、姓名 name、年龄 age和性别 sex,并且在 id_card 上建立了辅助索引(普通索引/非聚集索引)
如果现在有一个高频请求,要根据市民的身份证号查询他的姓名:
select name from user where id_card = xxx;
众所周知,这会导致回表查询,通过 id_card 这棵辅助索引树只能找到主键 id,然后需要再回到主键索引(聚集索引)树上根据主键 id 查找相应的 name。
所以,这个时候,我们可以建立一个 (id_card, name) 的联合索引来进行优化,对于这条语句来说,也就是覆盖索引,在这个高频请求上用到覆盖索引,不再需要回表查整行记录,大幅减少了语句的执行时间。
不过,索引字段的维护总是有代价的,如果为每一种查询都设计一个联合索引,索引是不是太多了?反过来说,单独为一个不频繁的请求创建一个联合索引是不是有点浪费了。因此在建立冗余索引来支持覆盖索引时就需要我们去做出一些权衡考虑了。
具体来说,我们应该怎么做呢?
最左前缀原则
B+ 树这种索引结构,可以利用联合索引的 “最左前缀” 来定位记录。
何为联合索引的最左前缀原则?
从本质上来说,联合索引也是一棵 B+ 树,不同的是联合索引的键值的数量不是 1,而是大于等于 2。我们来看下两个整型列组成的联合索引,假定两个键值的名称分别为 a、b
从图中可以看到多个键值的 B+ 树情况,键值都是排序的。通过叶子节点可以逻辑上顺序读取所有数据,就上面图中所示,即为 (1,1)、(1、2)、(2、1)、(2、4)、(3、1)、(3、2),数据是按照 (a, b) 的顺序进行存放。