目录
什么是索引
索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。
索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。说起加速查询,就不得不提到索引了。
为什么需要索引?
思考:如何在一个图书馆中找到一本书? 设想一下,假如在图书馆中没有其他辅助手段,只能一条道走到黑,一本书一本书的找,经过3个小时的连续查找,终于找到了你需要看的那本书,但此时天都黑了。为了避免这样的事情,每个图书馆才都配备了一套图书馆管理系统,大家要找书籍的话,先在系统上查找到书籍所在的房屋编号、图书架编号还有书在图书架几层的那个方位,然后就可以直接大摇大摆的去取书了,就可以很快速的找到我们所需要的书籍。索引就是这个原理,它可以帮助我们快速的检索数据。
一般的应用系统对数据库的操作,遇到最多、最容易出问题是一些复杂的查询操作,当数据库中数据量很大时,查找数据就会变得很慢,这样就很影响整个应用系统的效率,我们就可以使用索引来提高数据库的查询效率。
B-Tree和B+Tree
目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构, 我在这里分别讲一下:
B-Tree
即B树,注意(不是B减树),B树是一种多路搜索树。使用B-Tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。
B-Tree有如下一些特征:
- 定义任意非叶子结点最多只有M个子节点,且M>2。
- 根结点的儿子数为[2, M]。
- 除根结点以外的非叶子结点的儿子数为[M/2, M], 向上取整 。
- 每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)。
- 非叶子结点的关键字个数=指向儿子的指针个数-1。
- 非叶子结点的关键字:K[1], K[2], …, K[M-1],且K[i] <= K[i+1]。
- 非叶子结点的指针:P[1], P[2], …,P[M](其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树)。
- 所有叶子结点位于同一层。
有关b树的一些特性:
- 关键字集合分布在整颗树的所有结点之中;
- 任何一个关键字出现且只出现在一个结点中;
- 搜索有可能在非叶子结点结束;
- 其搜索性能等价于在关键字全集内做一次二分查找。
B树的搜索:从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复执行这个操作,直到所对应的节点指针为空,或者已经是是叶子结点。
例如下面一个B树,那么查找元素43的过程如下:
根据根节点指针找到18、37所在节点,把此节点读入内存,进行第一次磁盘IO,此时发现43>37,找到指针p3。
根据指针p3,找到42、51所在节点,把此节点读入内存,进行第二次磁盘IO,此时发现42<43<51,找到指针p2。
根据指针p2,找到43、46所在节点,把此节点读入内存,进行第三次磁盘IO,此时我们就已经查到了元素43。
在此过程总共进行了三次磁盘IO。
B+Tree
B+Tree属于B-Tree的变种。与B-Tree相比,B+Tree有以下不同点:
- 有n棵子树的非叶子结点中含有n个关键字(B树是n-1个),即非叶子结点的子树指针与关键字个数相同。这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(B树是每个关键字都保存数据)。
- 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
- 所有的非叶子结点可以看成是叶子节点的索引部分。
- 同一个数字会在不同节点中重复出现,根节点的最大元素就是b+树的最大元素