索引的数据结构?
答:通常索引的数据结构是B+树,比较小众的也有Hash结构,BitMap等。
Mysql数据库不支持BitMap索引。
索引的数据结构让检索更高效:
生成索引,建立二叉查找树进行二分查找;
生成索引,建立B-Tree结构进行查找;
生成索引,建立B+-Tree结构进行查找(mysql);
生成索引,建立Hash结构进行查找;
二叉查找树
特点:左子树的值均小于父节点,右子树的值均大于父节点;每个索引的存储块,存储的是关键字,指向子树的指针;使用二分查找。
时间复杂度:O(logn),查询效率很高
缺点:
1.数据库的数据可能面临增加和删除,慢慢的树就会演进成为一个线性二叉树。
2.每一次查找树节点,都会进行一次IO操作,当数据多的时候,性能也会降低。
B-Tree:平衡多路查找树
每个节点最多有m个孩子,那么这样的数就是m阶B-Tree。
每个索引的存储块,存储的是关键字,指向子树的指针,最多能有几个孩子,取决于存储块的容量以及数据库的相关配置,通常情况下,m是很大的。
B-Tree定义:
根节点至少包含两个孩子
树中每个节点最多含有m个孩子(m>=2)
除根节点和叶节点外,其他节点至少有ceil(m/2)个孩子(向上取整)
所有叶子节点都位于同一层
解释:
a)
关键字8,12是升序排列的
b)任意节点的关键字个数比它的孩子上限少一个
c)某节点最左边孩子的关键字小于该节点关键字值
3,5都比8小
某节点最右边孩子的关键字值均大于该节点的关键字值
剩下的孩子节点的关键字值在节点的关键字值之间
使用B-Tree的目的是让每个索引块尽可能存储更多的信息,尽可能减少IO次数。B-Tree的查询效率和二分查找树一样。
B+-Tree
B+树是B树的变体,其定义基本与B树相同,除了:
1.非叶子节点的子树指针与关键字个数相同
2.非叶子节点的子树指针p[i],指向关键字值[K[i],K[i+1])的子树
3.非叶子节点仅用来索引,数据都保存在叶子节点中(所有的搜索都会在叶子节点中终结;非叶子节点不存储索引,又能存储更多的关键字)
4.所有叶子节点均有一个链指针指向下一个叶子结点(一旦定位到某个叶子节点,就可以从该叶子节点横向跨子树做查询)
对2的解释:
10对应的子树的关键字值,大于等于10,小于20
结论:
B+Tree更适合用来做存储索引。
1.B+树的磁盘读写代价更低。B+树的内部节点并没有指向关键字具体数据的指针,也就是非叶子节点仅用来索引,不存放数据。因此其内部节点相对B树更小,如果将同一内部节点的关键字存放在同一盘块当中,这个盘块所能容纳的关键字就越多,一次读入内存中需要查找的关键字也就更多。IO读写次数降低。
2.B+树的查询效率更加稳定。由于内部节点并不是最终指向文件内容的节点,而只是叶子节点中关键字的索引,所以任何关键字的查找必须走一条从根节点到叶子节点的路,所有关键字查询的长度相同,每个数据的查询效率都是相同的,稳定的。
2.B+树更有利于对数据库的扫描。B树在提高了磁盘IO性能时,并没有解决元素遍历效率底下的问题,而B+树只需要遍历叶子节点,就可以解决对全部关键字信息的扫描,所以对于数据库中频繁使用的范围查询。比如查询大于10的数据,就只要查到关键字10,就可以顺着该叶节点的指针,向后面的节点进行查询。
Hash索引
根据Hash函数的运算,只需经过一次定位就可以查找到需要查询的数据所在的头,查询效率理论上高于B+树。
缺点:
1.仅仅能满足“=”,“IN”,不能使用范围查询。Hash索引比较的是进行Hash运算后的Hash值,所以他只能用于等值的过滤,不能用于基于范围的查询,因为经过Hash算法处理后的Hash值的大小关系并不能保证跟Hash运算前的完全一样。
2.无法被用来避免数据的排序操作
3.不能利用部分索引键查询。对于组合索引,Hash索引在计算Hash值的时候,是将组合索引键合并之后,再一起计算Hash值,而不是单独计算Hash值。通过组合索引的其中几个索引进行查询的时候,Hash索引无法被利用,而B+树是支持使用组合索引中的部分索引的。
4.不能避免表扫描。Hash索引是将索引键通过Hash运算之后,将运算结果和Hash值和所对应的行指针信息存放在一个Bucket中,由于不同索引键会存在相同的Hash值,所以即使取出满足某个Hash值的数据,也无法从Hash索引中直接完成查询。还是要通过访问Bucket中的实际数据,进行相应的比较。
5.遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高。
BitMap位图索引
当表中的某个字段只有几种值的时候,比如性别只有男女,为了实现在这个字段上进行高效的统计,使用位图索引是最佳的选择。不过目前很少数据库支持位图索引。位图索引的结构类似B+树,定位叶子节点,叶子节点包含指定键值的位图段。
关键字:Blue 1代表该位置是Blue,0代表该位置不是Blue。
位图段只要存储是与否,所以通常只需要一个Bit位来存放,因此一个叶子块能够存放非常多的Bit位来表示不同的行,因此用它来统计是非常快的。
缺点:
1.只适用于某个字段只有固定几个值的情况
2.锁的力度非常大,当尝试新增或删除某数据时,与他存在同一个位图上的数据都会被锁住。因为某行所在的位置顺序可能会因为数据的增加和删除发生改变。
所以位图索引不适合高并发的联机事务处理系统,适合并发较少统计较多的系统。