1、什么是索引?

索引是一种帮助数据库高效查找特定数据的数据结构。最基本的查询算法是顺序查找,逐条比对,这种算法在数量量不大的时候可能没有什么影响,但是一旦数据量较大时,就会很慢。除了顺序查找,还有许多高级的查找算法,比如二分法查找、二叉树查找,但是这个算法要求数据本身必须有特定的结构,二分法查找要求被检索的数据有序,二叉树查找只能应用于二叉树,很明显我们在数据库中存储的数据不满足这些特定的结构。所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构上实现高级查找算法。

2、B-Tree

目前大部分数据存储系统或文件系统都采用B-Tree或者其变种B+Tree作为索引结构。

为了描述B-Tree,我们把每个节点视为一个二元组 [key,value],key为记录的键值,每条数据记录,他们的键值也互不相同;data为数据记录。

这里先声明几个概念:

高度h:B-Tree树的层级高度。

出度d:B-Tree树单个层级的宽度。

B-Tree按照键值key检索的算法非常简单:

从根节点进行二分法查找,如果找到,则返回对应节点的data,否则,对相应区间的节点再次二分法查找,一直找到叶子节点,如果找到了就返回对应的data,如果没有找到,则返回null。

因此,出度d越大,高度h就越小,检索效率也会越高。

3、B+Tree

B-Tree有很多变种,B+Tree就是其中一种。mysql 数据库采用的就是B+Tre,它与B-Tree最大的不同就是它的非叶子节点不存放数据记录data。

4、为什么采用B-Tree或B+Tree

一般来说,索引本身也比较大,因此索引通常以索引文件的形式存储在磁盘中。我们都知道,计算机与磁盘的IO交互是比较耗时的,而与内存的交互速度只有磁盘IO的几百分之一,所以,一个优秀的索引必须要尽量少的发生磁盘IO。

由于磁盘IO的效率很低,为了提高效率,计算机并不是让磁盘严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存,这样做的理论依据就是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据通常也会被立即使用。预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。

数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。

5、索引实现

在mysql中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,这里主要讨论MyISAM和InnoDB两种存储引擎。

MyISAM的索引方式叫做非聚集索引,MyISAM的索引文件仅仅保存数据记录的地址,检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。它的主索引和辅助索引在结构上没有任何区别,唯一的不同就是主索引的key不允许重复,而辅助索引的key是可以重复的。

InnoDB的索引方式叫做聚集索引,InnoDB的数据文件本身就是索引文件。在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

InnoDB的辅助索引data域存储相应的主键的值而不是数据记录的地址,也就是说,InnoDB的所有辅助索引都引用主键作为data域。

聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

 

Logo

华为云1024程序员节送福利,参与活动赢单人4000元礼包,更有热门技术干货免费学习

更多推荐