mysql b树深度_简单了解平衡二叉树,以及B树、B+树、B*树,MySQL的优化(索引)...

简介

我们所知道的动态查找树有什么呢,动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ),B-tree/B+-tree/ B*-tree (B~Tree)。那么我们说的这几种树,前三种树都是比较典型的二叉树结构,查找的时间复杂度O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率。那么接下来我们就来简单的了解一下“平衡二叉树”、B-tree/B+-tree/ B*-tree (B~Tree)的原理,以及mysql的优化,下面进入我们的正题。

平衡二叉树

说到平衡二叉树,那么我们肯定得了解它的原理是什么呢,是怎么出现的呢。

平衡二叉树是基于二分法的策略提高数据的查找速度的二叉树结构。

平衡二叉树的特点又是什么呢。平衡二叉树是采用二分法思维把数据按规则组装成一个树形结构的数据,用这个树形的数据减少无关数据的检索,大大提高了检索的速度。

说到这,可能有些小伙伴不了解二分法的原理(说的是我这种的菜鸟)。会问什么是二分法呢,它又是怎么工作的呢。那么接下来我们下简单的了解一下,什么是二分法,二分法的工作原理。

先说一下二分法的定义(百度百科),二分法(Bisection method) 即一分为二的方法. 设[a,b]为R的闭区间. 逐次二分法就是造出如下的区间序列([an,bn]):a0=a,b0=b,且对任一自然数n,[an+1,bn+1]或者等于[an,cn],或者等于[cn,bn],其中cn表示[an,bn]的中点。

下面我们通过一个例子,真实了解一下什么是二分法。

现在我们创建一个数组int arr[] = new int[]{2, 20, 12, 11, 13, 30, 6, 22};

排序之后放入下面的数组中:

如果我们定义两边边界的数组下标,小的那边叫min,大的那边叫max,中间值就叫mid。min=0,max=arr. length-1,mid=(min+max)/2;在进行每一步的比较时,min<=max。如果我们是要查找数值为11值的下标。那么二分法的过程是什么呢。

第一步:mid = (0+7)/2=3;我们得到的下标为3的数据,arr[3]=12。进行值的比对,我们发现12>11,所以我们接下来需要在左边进行查找。min不变,max=mid-1。

第二步:mid = (0+2)/2=1;我们得到的下标为1的数据,arr[1]=6。进行值的比较,我们发现6<11,所以我们接下来需要在右边进行查找。min=mid+1;max不变。

第三步:mid = (2+2)/2=2;我们得到的下标为2的数据,arr[2]=11。进行值比较,我们发现11=11,是我们所需要找的数据,然后,我们停止查找,并返回mid的下标。

下面使用Java进行代码实现。

这里就不说结果了,自己进行试验,跟我们上面的推理是一样的。

二分法就简单介绍到这,下面我们继续回到我们平衡二叉树上,现在应该可以明白平衡二叉树的工作原理了吧。

平衡二叉树的数据结构组装过程的规则:

非叶子节点只能允许最多两个子节点存在,每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值(这里值是基于自己的算法规则而定的,比如hash值)。

平衡二叉树的层级结构:平衡二叉树的查询性能跟它的层级(h高度)成正比,为了保证树的结构左右两端数据大致平衡降低二叉树的查询难度一般会采用一种算法机制实现节点数据结构的平衡。平衡二叉树是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点总数的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。通过这样避免树形结构由于删除增加变成线性链表影响查询效率,保证数据平衡的情况下查找数据的速度近于二分法查找。

平衡二叉树的特点:

1. 非叶子节点最多拥有两个子节点

2. 非叶子节点大于左边子节点,小于右边的子节点

3. 树的层级差的绝对值不超过1

4. 没有重复数据的节点;

B树(B-tree)

定义:B树是一种平衡的多叉树。

一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:

1. 树中每个节点最多含有m个节点(m>=2)

2. 除根节点外每个节点的关键字数量大于等于ceil(m/2)-1个小于等于m-1个,非根节点关键字数必须>=2;(注:ceil()是个朝正无穷方向取整的函数 如ceil(1.1)结果为2)

3. 所有叶子节点均在同一层、叶子节点除了包含了关键字和关键字记录的指针外也有指向其子节点的指针只不过其指针地址都为null

4. 如果一个非叶节点有N个子节点,则该节点的关键字数等于N-1

5. 所有节点关键字是按递增次序排列,并遵循左小右大原则

定义一个三阶树(平衡三路查找树),如下图所示

B树和平衡二叉树最大的不同,是把每个节点的关键字增多了,B树在数据库中应用,更加充分的利用了磁盘块的原理(磁盘数据存储是采用块的形式存储的,每一个块的大小都是4K,每一次使用I/O进行数据读取时,都会把一个磁盘块的数据一次性读取出来)。通过增加节点的关键数量,降低了树的层级,更少的进行I/0操作,从而降低了数据查询的次数和复杂度,提高了数据查询的性能。

B+树

B+树是B树的一个升级版。为什么说是升级版呢,我们在上面的时候,说到了“叶子节点除了包含了关键字和关键字记录的指针外也有指向其子节点的指针只不过其指针地址都为null”,B+树相对于B树来说更好的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。为什么说B+树查找的效率要比B树更高、更稳定;我们先看看两者的区别。

1. B+树的非叶子节点不在存储关键字记录的指针,使得我们有更大的空间存储更多的关键字,在同样的数据下,降低了树的层级,加快查询速度。

2. B+树叶子节点保存了父节点的所有关键字和关键字记录的指针,每个叶子节点的关键字从小到大链接

3. B+树的根节点关键字数量和其子节点个数相等

4. B+的非叶子节点只进行数据索引,不会存实际的关键字记录的指针,所有数据地址必须要到叶子节点才能获取到,所以每次数据查询的次数都一样。

上面是自己创建的一个三路B+树,下面是网上的一个图,可以帮助我们更好的了解B+树的原理。

特点:

B+树只有在叶节点中存储关键字的指针,所以每个节点存储的关键字增多,树的层级也相对应的变少,树的查询性能跟它的层级(h高度)成正比,所以它的层级越少,查询速度也就越快,因为每次查找都要查到子节点,所以每次查询到额次数都是一样的,所以查询更加稳定。

B*树

B*树是B+树的变种,在B+树的基础上(所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针),B*树中非根和非叶子结点再增加指向兄弟的指针;B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)。给出了一个简单实例,如下图所示:

B+树和B*树有哪些不同点呢。

1. B+树初始化的关键字初始化个数是ceil(m/2),b*树的初始化个数为(ceil(2/3*m))

2. B+树节点满时就会分裂,而B*树节点满时会检查兄弟节点是否满(因为每个节点都有指向兄弟的指针),如果兄弟节点未满则向兄弟节点转移关键字,如果兄弟节点已满,则从当前节点和兄弟节点各拿出1/3的数据创建一个新的节点出来

B*树分配新结点的概率比B+树要低,空间使用率更高。

MySQL优化

这里我们就讲一下MySQL中的优化,具体讲什么呢,我们这里就讲一下索引。当数据量比较大的时候,我们查询会比较耗时,创建适当的索引,可以加快我们的查询速度。

本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等。我们接触最多的索引就是BTree索引,我们在上文中已经讲解了B树和B+树的工作原理。那么我们接下来,了解一下,创建索引需要那些条件呢,或者换句话说,什么样的数据,才适合建立索引呢。

1. 选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。

2. 为经常需要排序、分组和联合操作的字段建立索引

经常需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。如果为其建立索引,可以有效地避免排序操作。

3. 为常作为查询条件的字段建立索引

如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建立索引,可以提高整个表的查询速度。

4. 限制索引的数目

索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

5. 尽量使用数据量少的索引

如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR(100)类型的字段进行全文检索需要的时间肯定要比对CHAR(10)类型的字段需要的时间要多。

6. 尽量使用前缀来索引

如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。

7. 删除不再使用或者很少使用的索引

表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。

8. 小表不应建立索引;包含大量的列并且不需要搜索非空值的时候可以考虑不建索引

添加和删除索引的情况:

1、表的主键、外键必须有索引;

2、数据量超过300w的表应该有索引;

3、经常与其他表进行连接的表,在连接字段上应该建立索引;

4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;

5、索引应该建在离散性高的字段上;

6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;

7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:

A、正确选择复合索引中的主列字段,一般是选择性较好的字段;

B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;

C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;

D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;

E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;

8、频繁进行数据操作的表,不要建立太多的索引;

9、删除无用的索引,避免对执行计划造成负面影响;

就先讲到这里,这是我自己的一些简单理解(索引的大部分摘抄自别的文章,看别人写的比较好,自己的语言组织能力有限,拿过来用一下)。

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值