索引:索引是帮忙MySQL高效获取的排好序的数据结构
索引数据结构:
- 二叉树
- 红黑树
- Hash表
- B-Tree
1.二叉查找树(Binary Search Trees)
左节点比父节点要小,右节点比父节点要大。他的高度决定的查找效率。
平衡二叉查找树:
非正常的倾斜二叉查找树:
如果某一列数据遇到像‘倾斜二叉查找树’,那么这个二叉树索引,其实就蜕化成了“链表”,查询此列数据还是全表扫描的方式,就失去了加索引的意义。
树在插入的时候非常有可能导致倾斜,不同的插入顺序会导致树的高度不一样,而树的高度直接影响了树的查找效率。不平衡的二叉查找树自然查找效率更低。
2.红黑树(Red-Black Trees)
本质还是一个二叉树,但是他叫做二叉平衡树。解决二叉树一边倒的可能性。平衡树在插入和删除的时候,会通过旋转操作将树的左右节点达到平衡。
Java中的HashMap和TreeSet,Java8中HashMap的实现因为用红黑树代替链表(链表长度>8)时。
红黑树规则定义:
1.任何一个节点都有颜色,红色或黑色
2.根节点是黑色的
3.父子节点之间不能出现两个连续的红节点
4.任何一个根节点,遍历到他的子孙节点,所经过的黑色节点数必须相同
5.空节点被认为是黑色的
因为以上规则的限制,保证了红黑树的自平衡。红黑树从根到叶子节点的最长路径不会超过最短路径的2倍。
3.Hash索引
hash是一种key-value形式的数据结构。实现一般是数组+链表的结构,通过hash函数计算出key在数组中的位置,然后如果出现hash冲突就通过链表来解决(拉链法)。当然还有其他的解决hash冲突的方法。hash这种数据结构是很常用的,比如我们系统使用HashMap来构建热点数据缓存,存取效率很好。
hash结构存数据首先通过计算key的hash值来确定其在数组中的位置,如果有冲突就在该数组位置建一个链表。这样很明显有几个问题:
即使是具有相同特征的key计算出来的位置可能相隔很远,连续查询效率低下。即不支持范围查询。
hash索引存储的事计算得到的hash值和行指针,而不存储具体的行值,所以通过hash索引查询数据需要进行两次查询(首先查询行的位置,然后找到具体的数据)
hash索引查询数据的前提就是计算hash值,也就是要求key为一个能准确指向一条数据的key,所以对于like等一类的匹配查询是不支持的。
所以我们可以知道的是hash索引适用于快速选取某一行的数据。范围查找的这种搜索,Hash无法进行满足。
4.B+ 树
而在MySQL索引中虽然也使用了树结构,但是并不是使用的二叉树。因为在数据库中数据最终都是存放在磁盘上的,而如果树的节点过多的话,那么在节点之间转移会花费较多的时间。在MySQL的实现中选择将更多内容放在同一个节点,对同一个节点的操作转入在内存中完成,减少在外存中节点之间转移的次数,以达到提高效率的目的。这就是B+Tree,在B+Tree的实现中一个三层的树结构就基本上可以满足我们几乎所有的需求了。
3.红黑树效率如此之高,MySQL为何不采用
在实际场景应用当中,MySQL表数据,一般情况下都是比较庞大、海量的。如果使用红黑树,树的高度会特别高,红黑树虽说查询效率很高。但是在海量数据的情况下,树的高度并不可控。如果我们要查询的数据,正好在树的叶子节点。那查询会非常慢。故而MySQL并没有采用红黑树来组织索引。