数据库索引融会贯通

索引的各类规则纷繁复杂,不了解索引的组织形式就没办法真正地理解数据库索引。经过本文,你能够深刻地理解数据库索引在数据库中到底是如何组织的,今后之后索引的规则对于你将变得清清楚楚、明明白白,不再须要死记硬背。数据库

顺畅地阅读这篇文章须要了解索引联合索引汇集索引分别都是什么,若是你还不了解,能够经过另外一篇文章来轻松理解——数据库索引是什么?新华字典来帮你设计

这篇文章是一系列数据库索引文章中的第二篇,这个系列包括了下面四篇文章:3d

  1. 数据库索引是什么?新华字典来帮你 —— 理解指针

  2. 数据库索引融会贯通 —— 深刻code

  3. 20分钟数据库索引设计实战 —— 实战cdn

  4. 数据库索引为何用B+树实现? —— 扩展blog

这一系列涵盖了数据库索引从理论到实践的一系列知识,一站式解决了从理解到融会贯通的全过程,相信每一篇文章均可以给你带来更深刻的体验。索引

索引的组织形式

经过以前的内容,咱们已经对数据库索引有了至关程度的抽象了解,那么在数据库中,索引实际是以什么样的形式进行组织的呢?同一张表上的多个索引又是怎样分工合做的呢?get

目前绝大多数状况下使用的数据库索引都是使用B+树实现的,下面就以MySQL的InnoDB为例,介绍一下数据库索引的具体实现。it

汇集索引

下面是一个以B+树形式组织的拼音索引,在B+树中,每个节点里都有N个按顺序排列的值,且每一个值的中间和节点的头尾都有指向下一级节点的指针。在查找过程当中,按顺序从头至尾遍历一个节点中的值,当发现要找的目标值刚好在一个指针的前一个值以后、后一个值以前时,就经过这个指针进入下一级节点。当最后到达叶子节点,也就是最下层的节点时,就可以找到本身但愿查找的数据记录了。

image.png

在上图中若是但愿找到字,那么咱们首先经过拼音首字母在根节点上按顺序查找到了XY之间的指针,而后经过这个指针进入了第二级节点···, xia, xian, xiang, ···。以后在该节点上找到了xianxiang之间的指针,这样就定位到了第519页开始的一个目标数据块,其中就包含了咱们想要找到的字。

由于拼音索引是汇集索引,因此咱们在叶子节点上直接就找到了咱们想找的数据。

非汇集索引

下面是一个模拟部首索引的组织形式。咱们由根节点逐级往下查询,可是在最后的叶子节点上并无找到咱们想找的数据,那么在使用这个索引时咱们是如何获得最终的结果的呢?回忆以前字典中“检字表”的内容,咱们能够看到,在每一个字边上都有一个页码,这就至关于下面这一个索引中叶子节点上字与字中间的指针,这个指针会告诉咱们真正的数据在什么地方。

image.png

下图中,咱们把非汇集索引(部首索引)和汇集索引(拼音索引)合在一块儿就能看出非汇集索引最后到底如何查找到实际数据了。非汇集索引叶子节点上的指针会直接指向汇集索引的叶子节点,由于根据汇集索引的定义,全部数据都是按汇集索引组织存储的,因此全部实际数据都保存在汇集索引的叶子节点中。而从非汇集索引的叶子节点连接到汇集索引的叶子节点查询实际数据的过程就叫作——回表

image.png

全覆盖索引

那么若是咱们只是想要验证字的偏旁是不是双耳旁“阝”呢?这种状况下,咱们只要在部首索引中下游的叶子节点中找到了字就足够了。这种在索引中就获取到了SQL语句中须要的全部字段,因此不须要再回表查询的状况中,这个索引就被称为这个SQL语句的全覆盖索引

在实际的数据库中,非汇集索引的叶子节点上保存的“指针”就是汇集索引中全部字段的值,要获取一条实际数据,就须要经过这几个汇集索引字段的值从新在汇集索引上执行一遍查询操做。若是数据量很少,这个开销是很是小的;但若是非汇集索引的查询结果中包含了大量数据,那么就会致使回表的开销很是大,甚至超过不走索引的成本。因此全覆盖索引能够节约回表的开销这一点在一些回表开销很大的状况下就很是重要了。

范围查询条件

image.png

上图是一个联合索引idx_eg(col_a, col_b)的结构,若是咱们但愿查询一条知足条件col_a = 64 and col_b = 128的记录,那么咱们能够一路肯定地往下找到惟一的下级节点最终找到实际数据。这种状况下,索引上的col_acol_b两个字段都能被使用。

image.png

可是若是咱们将查询条件改成范围查询col_a > 63 and col_b = 128,那么咱们就会须要查找全部符合条件col_a > 63的下级节点指针,最后不得不遍历很是多的节点及其子节点。这样的话对于索引来讲就得不偿失了,因此在这种状况下,数据库会选择直接遍历全部知足条件col_a > 63的记录,而再也不使用索引上剩下的col_b字段。数据库会从第一条知足col_a > 63的记录开始,横向遍历以后的全部记录,从里面排除掉全部不知足col_b = 128的记录。

这就是范围条件会终止使用联合索引上的后续字段的缘由。