本文正在参加「技术专题19期 漫谈数据库技术」活动
这个是MySQL使用最频繁的,默认的索引类型,一般情况下不做强调的化,使用的就是这种类型的索引,最直接的理解就是,以B-Tree结构存放索引数据,今天我们从数据结构聊聊B-Tree索引。
树结构
树是数据结构当中的一种基础的数据结构,我们先回顾一下他的定义:
树是n(n>=0)个节点的限集,n为0的时候为空树,n不为0就是非空树,在任意一棵非空树当中,(1)有且只有一个根节点,(2)当n>1时,根节点之外其余的节点可以分成m(m>0)个互不相交的有限集,其中每个集合本身又是一颗树,被称为根的子树。
树结构是典型的一对多的结构。
如图:
(1)A是根节点,B,C是A的子树,F是C的子树。
(2)B子树是A的左子树,C子树是B的右子树。
(3)A节点是B或者C的双亲节点,B或者C是A的子节点
(4)B和C节点互为兄弟节点,当然 D和E,G和H也是。
(5)节点的子节点个数称为节点的度,比如B的度就是2,树的度指的是当前所有节点最大的度,这里也是2
(6)树有几层,称为树的深度,当前树的深度是4
(7)没有子节点的节点被称为叶子节点,比如:D,E,G,H
(8)非根,非叶子节点的节点就是内部节点,比如:B,C,F
BTree
上面说的树本身就是一个基础的数据结构,并没有什么特殊的地方,但是基于树的一对多性质,可以发现,如果按照树的结构有规律的安排节点的元素,可以很方便的进行查找操作,因为,父节点可以概况出子节点的范围,比如:
这里父节点都大于子节点,右节点都大于左节点,所以如果查询一个数字的话,比如5:
(1)先查询9不是
(2)然后看4和8子树,因为子节点都小于父节点,所以直接找8,然后找7
(3)7下面先找小的节点,5查找到了
这种方式可以有效的避免全文检索,提升查询的效率,所以,如果在这种思路下,把树的结构和上面的逻辑进行结合,是不是可以设计出一种查询方便的树,BTree就是其中的一种。
BTree里面的B是Balance的意识,BTree全称是多路搜索树(这个和我们学习的二叉树还是有区别的):
1.定义任意非叶子结点最多只有M个儿子;且M>2;
2.根结点的儿子数为[2, M];
3.除根结点以外的非叶子结点的儿子数为[M/2, M];
4.每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
5.非叶子结点的关键字个数=指向儿子的指针个数-1;
6.非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
7.非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
8.所有叶子结点位于同一层;
看上去很复杂,其实这样查找很方便,每次查找都是从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点:
BTree比二叉树的度要大,遍历效率更高。
MySQL B-Tree索引
mysql 默认索引采用BTree思路来存储索引,所以基于索引列的查询会快很多,当然innoDB是通过B+Tree实现的(个人感觉B-Tree和B+Tree区别就是B+Tree非叶子节点不存储真正的数据。),使用MySQL的B-Tree索引可以完成以下工作:
1、全值匹配,匹配索引列的完整字段。
2、从左匹配前缀,比如 Tom Json,匹配Tom
3、匹配范围
4、多条件匹配,比如 匹配Tom并且名字以J开头的。
5、个人感觉最牛的,B-Tree索引可以实现不访问表,直接访问索引查询,因为B-Tree节点上存储真正的数据。
当然也有一些局限的地方需要注意:
1、必须从索引列的最左边进行匹配,比如Tom Json这样的数据,如果检索 Json,那么索引就没有效果了。
2、不可以跳过索引当中的列
3、范围查询后面的过滤条件,索引失效,比如:
select * from person where first_name like "%o%" and last_name = "json";
这样,last_name的索引效果就没有了。
最后,在第一次通过mysql研究B-Tree之后,有一种感觉,就是:最糟糕的操作就是把树状结构搞成了线性结构,比如之前老觉得不错的树结构拍扁,其实性能也就下来了,所以大家可以在学习数据库的过程当中,结合自己对数据结构的理解,会有很多领会,还是请大家多多指点。
本文正在参加「技术专题19期 漫谈数据库技术」活动