1.选择标准
索引选数据结构只有一个标准:磁盘IO次数,越少越好
索引是存储在外部磁盘上的,对于关系型数据库,当数据量比较大的时候,索引有可能达到几个G甚至更多,不可能全部加载完,只能逐一加载,每次加载都会耗时,所以加载次数越少越好
2.各种数据结构分析
2.1可以是Hash表吗?
不可以
- Hash是通过某种确定的算法将输入变输出,相同的输入总会得到相同的输出
- Hash中像HashMap,增删查改的平均都是O(1),单从效率方面是比B+树快好几倍
- 哈希在处理数据相等时效率非常高
那为什么不选Hash?
- 原因1:Hash索引只支持等于、不等于、
in
查询.如果进行范围查询,哈希的复杂度会退化成O(n),而树索引仍然高效O(log2N) - 原因2:哈希存储数据无序,因为哈希值无序,所以存储的数据也无序,如果使用
ORDER BY
查询,数据会重新排序 - 原因3:联合索引时,Hash会将几个索引值合并计算,无法对单独的一个或几个索引进行查询
- 原因4:如果索引列的重复值比较多(比如性别、年龄),Hash会发生哈希冲突,导致效率大大降低,可能会O(n)
Hash索引的适应场景:
虽然树索引使用范围更广,但也有一些场景使用Hash索引效率更高,比如键值型数据库中,Redis存储的核心就是哈希表
Innodb本身虽然不支持哈希索引,但是提提供自适应哈希(Adaptive Hash Index
),如果某个数据经常被访问,就会将这个数据放入Hash表中,下次访问可以直接取出,这样树索引也有了哈希的优点。
2.2 可以是二叉搜索树或者红黑树吗?
不可以
-
二叉搜索树每个节点只能有两个子节点,即度为2,且左节点<根节点<右节点
-
最基础的二叉搜索树(
Binary Search Tree
)查找规则如下:如果key大于根节点,去右子树;如果key小于根节点,去左子树;如果等于根节点,返回根节点;
正常情况O(log2N):
特殊情况O(n):
深度过大,退化成线性,类似链表
为什么不可以? -
二叉搜索树的平均查找效率是O(logN)
-
如果数据很多的话,二叉搜索树最多俩分支,所以树的深度会很大,查找效率其实不高
-
如果是范围查找还需要对二叉树进行中序遍历(二叉树的中序遍历有序),和上面的链表一样是O(N)不高效
2.3 可以是AVL树吗?
本质可以,但为了更高的效率不选它
- 2叉树时,如果数据非常大,深度依然很大,效率并不高
- 拿来当索引时,尽量往N叉树方向发展
AVL树
- AVL树又被称为平衡二叉搜索树(
Balanced Binary Tree
),特点:它可以是一颗空树或它的左右两个子树的高度差小于1,并且左右子树都是平衡树.
虽然不会退化成O(N),但是数据非常多时,树的深度依然很高,如下图:
如何解决这个问题?
可以将2叉树变成N叉树,比如相同数据情况下,将2叉树变成3叉树:
总结:
二叉树或者AVL树可以用来作为数据库索引,但是尽量往N叉树的方向发展,降低树的高度,才能更符合索引的查找特性.
可以用树作为索引的数据结构,但是树越“矮胖”越好.
2.4 可以是B-树吗?
本质可以,但是为了更高的效率不选它
B-树和二叉树的差异
- 结点不再限于2个分支,可以有n个分支
- 结点不只存1个数据,可以存多个数据
- 节点存储数据个数和度有关 度=存储数据个数+1
- 在每个节点中查找时,不再限于2分查找,可以是N分查找,效率更高
- 在非叶子节点中也存有数据,如果和非叶节点中的数据相同,可以直接返回
B-树
- B-树(
Balance-Tree
),多路平衡查找树,一个节点最多可以有m
个节点,m
就称为B-树的阶,每个节点中包括关键字和子节点的指针,关键字中附带数据.对于一个100阶的B-树,在第3层就可以储存100万的索引数据,在大量索引数据的情况下,B-树是非常合适的.
B-树的特性
- 根节点最少有
2
个节点; - 每个节点最多可以有
m
个节点; - 除了根 叶子节点外,其余节点最少要有
m/2
个节点 - 所有节点的子节点个数可以不相同,但最少
m/2
个 - 叶子节点必须在同一层中
- 增加和删除节点时,如果不平衡,B树会自动调整节点的位置来保持平衡(旋转)
- 关键字遍布全树,即叶子和非叶子节点中都存放数据
- 每一次搜索相当于对关键字进行一次二分查找
2.5 可以是B+树吗?
可以,官方推荐+默认,真实的索引结构
- B+树是B-树的进阶,本质上也是多路搜索树
- B+树适合文件索引场景
B+树和B-树的差异
- B+树有几个分支就有几个关键字,而B-树 分支=关键字+1
- B+树父节点的关键字在子节点中都能找到,并且一般父节点的关键字是子节点关键字中最大或者最小的那个
- B+树只有叶子节点保存数据,而B-树叶子 非叶子节点都保存数据
- B+树所有关键字都在叶子节点出现,而B-树只出现部分关键字
为什么B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?
1.B+树的磁盘读写次数少
B+树的节点中不含有指针,比B-树的节点小,如果把左右的关键字段放入节点中,该节点容纳的关键字的数量就更多,一次性读入内存的关键字就越多,相对的查找次数就越低.
2.B+树的查询效率更稳定
B+树的所有的数据都存放在叶子节点,每次查询数据的路径长度差不多,查询效率相当,而B-树在非叶子节点中也存放数据,不同数据查询的路径长度不同,查询效率就不同,所以稳定性差一些。