窥视数据库索引

1. 索引简介

在讲解索引技术之前,让我们来重现两个生活场景。

1)在新华字典中查询“索引”这个词。一般情况,我们会直接在字典的目录按拼音找到“s”(或者按笔画),然后定位到“索”,最后找到“索引”对应的页码。

2)在图书馆中借阅《数据库系统概念》。一般情况,我们会按照图书分类,先找到计算机科学分类的书架,然后找到数据库的书架,最后再定位到《数据库系统概念》;当然如果我们目标明确,可以直接在图书馆系统中查询书目的“索引码”,然后根据索引码再去定位书架。

以上两个生活场景中,我们都用到了索引的概念,新华字典中的目录、图书馆的索引码都是索引概念的具体实现。

在计算机中,索引是文件系统或数据库实现时,为了能够快速定位、更新记录,而引入的一种数据结构。数据库中一般采用树或散列来组织索引,索引节点会存储记录本身或指向记录的指针。索引的两个个主要关键点:

1)搜索码(search key):新华字典的目录中的拼音或笔画;图书馆例子中的图书分类号

2)数据结构:顺序结构、树、散列

2. 数据库索引的数据结构

2.1 顺序索引

如字典目录和图书馆索引一样,顺序索引按顺序存储搜索码的值,并将搜索码与包含该搜索码的记录建立映射关系。顺序索引又分为稠密索引和稀疏索引。

稠密索引(dense index):每一条索引记录(index record)都会有一个对应的索引

稠密索引

稀疏索引(sparse index):索引指向的是存储索引记录的磁盘块,而不是索引记录本身的地址。与稠密索引相比,稀疏索引利用了操作系统在读磁盘信息时读的是磁盘块这个特性(磁盘块一般为4KB)。

稀疏索引

多级索引:当数据库存储的数据量特别大时,会造成稀疏索引本身占的空间很大,这样会带来两个问题1)索引太大导致无法直接放入内存,增加读索引开销;2)索引太大造成查询索引次数的增加,从而导致查询性能降低。这其实又回到了问题本身,就是当数据量特别大时如何高效查询数据,按照这个想法,我们可以对索引本身建立索引,此种索引称为多级索引。

多级索引

2.2 B+树索引

B+树索引是一种多级索引,它是B树(二叉树)的一个扩展形式。参考百度百科的信息,对B+树的描述如下。

B+树是应文件系统所需而出的一种B树的变型树。一棵m阶的B+树和m阶的B树的差异在于:
1)有n棵子树的结点中含有n个关键字,每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点
2)所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3)所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。
通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

B+树的节点分为内结点和叶子结点。内结点只存放搜索码和子女指针;叶子结点保存搜索码和附属数据(指向索引记录的指针)。

B 树

 B Tree

PS:叶子结点都有指向下一个结点的指针,方便通过索引查找某一区间内的数据。另外,在多个事务并发操作、访问同一节点时,如果更新节点的事务导致该节点发生了分裂现象,则同时拿到该节点位置的查询事务可能在该节点中找不到目标数据项,此时需要继续在下一个节点中查询,直至找到目标数据项。

2.3 散列索引

散列技术有两个关键点:1)Hash函数的设计;2)存储方式的选择;

Hash函数在大部分时间内可以保证程序可以在O(1)时间内计算出索引记录桶的存储位置index=hash(search key),所以可以避免过多的索引结构访问。

Hash函数设计关键点:

1)保证索引记录均匀分布。每个桶获得的搜索码数量应该是相等的。

2)保证索引记录随机分布。每个桶获得的搜索码值应该是随机的,不受搜索码值本身影响。

常见的散列存储方式:

1)开散列(open hashing)。当桶溢出时,增加溢出桶。如下图所示。

2)闭散列(close hashing)。当桶溢出时,使用其他还有空间的桶。

溢出链

2.3.1静态散列

是一种需要固定桶地址集合B的散列技术,这种技术的hash()函数(一般采用除余法)会桶节点个数的影响。相同的搜索码,在桶节点发生改变前后hash(search key)值会发生变化。这种变化会影响到绝大多数的搜索码的映射关系。

2.3.2动态散列

动态散列又称为可扩展散列或一致性散列(consistent hash),它与静态散列表结构的区别主要在于增加了以下内容:
1)为桶引入了一个间接层,即用一个块的指针数组来表示桶,而不是用数据块本身组成的数组来表示桶;
2)指针数组能增长,它的长度总是2的幂,因此每次增长桶的长度都翻倍;
3)不是每一个桶都有一个数据块,如果某些桶的数据可以放入一个块中,则这些桶可能共用一个块;
4)散列函数为每个键计算一个K位二进制序列,但无论何时桶的数目都使用从序列第一位开始的若干位,此位数小于K。

动态散列可以保证桶改变前后,hash()函数只会对一小部分搜索码的映射产生影响。如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区。(当缓冲区大小变化时Consistent hashing尽量保护已分配的内容不会被重新映射到新缓冲区。)

3. 数据库索引的使用

常见的主要由主键索引(唯一索引的特例)、唯一索引、联合索引等

这块后续研究后在专门介绍

 

References:

1. idber, 深入理解DB2索引(Index), http://blog.csdn.net/idber/article/details/8096941

2. Baidu百科, B+树, http://baike.baidu.com/view/1168762.htm

3. Baidu百科, 可扩展散列表, http://baike.baidu.com/view/2246537.htm

4. Baidu百科, 一致性哈希, http://baike.baidu.com/view/1588037.htm

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值