MySQL学习笔记(4)

来源:互联网 发布:js鼠标移动显示图片 编辑:程序博客网 时间:2024/05/30 19:33

索引与算法
由于InnoDB采用B+树进行索引,所以要了解索引与算法首先要了解树。

一、 树的分类(定义和一些性质在此就不多讲了)
普通的树、二叉树、二叉查找树、AVL树、伸展树、B-树
– 普通的树
一个节点可以有多个子节点(儿子)。(文件系统就是树结构)
– 二叉树
二叉树的一个节点最多有两个子节点。
– 二叉查找树
既是二叉树则一个节点最多有两个子节点,主要用途为查找。
二叉查找树树的每个节点,其左子树的所有节点值应小于该节点值,其右子树的所有节点值应大于该节点值。
二叉查找树
这是一棵二叉查找树
非二叉查找树
这个则不是二叉查找树
– AVL树
带有平衡条件的二叉查找树,一个AVL树其每个节点的左子树和右子树的高度最多差1,如下所示:
AVL树非AVL树
– B树(也是查找树)
B树有以下特点:
树的根或者是一片树叶,或者其儿子数要在2到M(树的阶数)之间。
除了根外,所有非树叶节点的儿子数在M/2到M之间。
所有的树叶都在相同的深度上。
在B树中所有的数据都在树叶上。
对于每个节点,从左到右,其子树的的关键字都小于下一个子树的关键字。
B树一般用于数据库中存储数据(数据在叶子上存储)。
对于B树现在不做更多介绍了(小白我也没怎么看懂),大家有兴趣的可以找些数据结构与算法的书籍看一下。

二、树的遍历(二叉树)
有三种遍历方法:前序遍历、中序遍历和后序遍历。

如上图提到的AVL树
前序遍历的结果为:5 2 1 4 3 8 7
中序遍历的结果为:1 2 3 4 5 7 8
后序遍历的结果为:1 3 4 2 7 8 5

树的遍历是通过递归调用实现的。下面就着重讲一下递归调用实现树的遍历:

在说明树的遍历实现之前小白觉得有必要讲一下递归调用的有关知识:
递归算法的特点:
(1)递归是在过程或函数中对自己的调用。
(2)使用递归算法必须有明确的递归结束条件,称递归出口,否则递归会无限次进行下去,必将导致程序或者系统崩溃。
(3)递归使代码非常简洁,但是运行效率不高。
(4)每一次的递归调用,系统都会为其返回点、局部变量等开辟栈来存储,所以递归次数过多容易造成栈溢出等。
看一个递归调用的图示:
简单函数的递归调用
由此图我们大致可以写出程序代码:

int fact(x){    if(x <= 1)        return 1;    return x*fact(x-1);}

共调用6次,结束条件为x<=1.(此图来源网络)
这里有一个点要理解清楚:每次调用后return并没有完全返回,因此函数栈是一直存在的,当x<=1时return 1函数栈此时销毁并返回1;然后上一级return 2*fact(1),函数栈销毁;然后return 3*fact(2),函数栈销毁;然后。。。

通过上面的讲解大家应该对递归调用有了一定的认识,那么现在我们回到自己的主题上,树的遍历。
– 前序遍历
前序遍历
前序遍历的递归实现:

preorder_tree(ptree T)  //T为树节点指针{    if(T != NULL)    {        visit(T);  //访问当前节点        preorder_tree(T->leftchild);  //访问左子树        preorder_tree(T->rightchild);  //访问右子树    }}

– 中序遍历
中序遍历
中序遍历的递归实现:

inorder_tree(ptree T){    if(T != NULL)    {        inorder_tree(T->leftchild);  //访问左子树        visit(T);  //访问当前节点        inorder_tree(T->rightchild);  //访问右子树    }}

– 后序遍历
后序遍历
后序遍历的递归实现:

postorder_tree(ptree T){    if(T)    {        postorder_tree(T->leftchild);  //访问左子树        postorder_tree(T->rightchild);  //访问右子树        visit(T);  //访问当前节点    }}

三、InnoDB存储引擎采用B+树来进行数据的查找和索引。
(1)B树和B+树的区别如下:
– 从指针角度理解B树和B+树的区别
– 讲解了B树、B+树、B-树和B*树
通过这两个链接相信能对“B”有一个更好的理解。
(2)现在来讲讲InnoDB存储引擎中通过B+树对数据的插入操作。
《MySQL技术内幕:InnoDB存储引擎》这本书中有一个很好的例子,本处照搬已做日后回顾:
首先B+树的插入要满足下表的情况:
B+树插入的3种情况
如下一棵B+树我们想要插入28这个键值,根据上表直接插入即可
B+树
顺便说一句,B+树数据是顺序安放的。插入结果如下:
插入28的B+树
很简单吧,嘿嘿,接下来就有些难以理解了。
我们继续插入70这个键值,先上结果,大家可以看结果并根据上表想想是如何实现的。
插入70后的B+树
根据上表我们知道此事要插入的叶子节点已经满了,而索引节点还没有,因此对叶子节点进行拆分。
好吧,让我们继续插入95。结果如图:
插入95后的B+树
因为索引节点和叶子节点都满了,这里我们要先去拆分索引节点,根据表格所说索引节点第一步拆分后是这样的:
60->(25,50),(75)
然后拆分叶子节点,中间值85被作为索引键值提升:
60->(25,50),(75,80)
然后叶子节点拆分并插入新值的结果应该比较明显了。
(3)B+树的删除操作
B+树的删除操作是根据填充因子的变化来做删除的。这里有一个链接然后结合我根据读书的理解,希望能帮到更多的人。
填充因子
再看《MySQL技术内幕:InnoDB存储引擎》书上的例子。
B+树删除操作的3种情况
如上图插入95的B+树,对其删除70操作(默认填充因子50%)。结果如下:
删除70
已知删除70后,叶子节点的填充量仍为50%=填充因子,因此直接删除即可(小白自己的理解)。
现在删除25,结果如下:
删除25
对于叶子结点来讲删除25后存储量仍为50%=填充因子,因此可以直接删除,但是25还存在于索引节点当中,因此索引节点也要删除,并用28来替代。
最后我们删除60,结果如下:
删除60
如图,因为删除60后,叶子结点存储量<50%,因此需要合并叶子节点,又因为60也在索引节点中,所以索引节点删除后也要合并索引节点。
(4)B+树的索引
B+树索引的本质就是在数据库的实现。
数据库中B+树索引分为两种:聚集索引和辅助索引。聚集索引和辅助索引的区别在于叶子节点存放时否是正行数据。
聚集索引
聚集索引会根据每张表的主键创建一个B+树,每个叶子节点(数据页)都通过双向链表连接。
辅助索引
对辅助索引,叶子节点不保存行记录的所有数据。叶子节点中有一个书签可以告知存储引擎到哪里可以找到与索引对应的数据。每张表可以有多个辅助索引。存储引擎会遍历辅助索引并通过叶级别的指针(我理解就是书签)获得指向主键索引的主键,再通过主键索引找到完整的行记录。
四、哈希算法
哈希表在数据库应用中的作用也是不可取代的。但是这里不准备讲哈希表以及哈希算法了,大家可以上网搜索一下。简单来说哈希算法就是将关键值放入哈希函数中,得到对应的数值。


本文参考《MySQL技术内幕:InnoDB存储引擎》和网络知识所写。

原创粉丝点击