Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1734296
  • 博文数量: 107
  • 博客积分: 1715
  • 博客等级: 上尉
  • 技术积分: 3168
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-18 18:42
个人简介

阿里巴巴DBA,原去哪儿网DBA。专注于MySQL源码研究、DBA运维、CGroup虚拟化及Linux Kernel源码研究等。 github:https://github.com/HengWang/ Email:king_wangheng@163.com 微博 :@王恒-Henry QQ :506437736

文章分类

全部博文(107)

文章存档

2014年(2)

2013年(38)

2012年(67)

分类:

2013-01-04 17:54:07

目的

       MySQL数据结构TREE是指红黑树(RB-TREE)数据结构及相关操作,红黑树是平衡搜索树的一种,通过结点的颜色,使得二叉搜索树近似于平衡,保证在最坏情况下基本动态集合操作的时间复杂度O(lgn)。该结构在MySQL中主要应用在myisam存储引擎的全文搜索及相关处理过程、heap键值定义数据结构HP_KEYDEF中。

       尽管红黑树在MySQL中的应用较少,但是红黑树在数据结构及算法方面的重要性毋庸置疑。因此,本文一方面简单介绍红黑树的性质和基本操作,另一方面重点分析MySQL中红黑树数据结构的设计和实现。

红黑树基础

       红黑树结构的性质和基本操作的介绍和分析的文章很多,特别推荐《算法导论》[1]一书中对该部分的介绍,非常详尽。另外,博文《教你透彻了解红黑树[2]中,根据《算法导论》红黑树的介绍,更进一步分析了红黑树。特别推荐转载的《理解红黑树[3-4]技术博客中,对红黑树实现的细节部分有进一步的阐述和分析。

       尽管有以上丰富的参考信息,为了便于理解一下MySQL中红黑树的设计,本文给出红黑树的性质,具体内容如下。

性质:

       1、每个结点或是红色的,或是黑色的。

       2、根节点是黑色的。

       3、每个叶结点(NIL)是黑色的。

       4、如果一个结点是红色的,则他的两个子结点都是黑色的。

       5、对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。

基本操作:

       由于红黑树是近似平衡的二叉搜索树,因此,在操作过程中,需要进行结点的平衡调整。红黑树的基本操作主要是旋转操作,包括左转、右转(很多文章中介绍,还有其他旋转操作,实际上其他所有的旋转操作都可以通过这两种旋转操作来实现)。

       然而,红黑树在旋转的同时,还需要对结点的颜色作调整。根据红黑树的性质,分为多种情况,具体参考《算法导论》中给出的详细分析过程。

数据结构

       通过以上红黑树的基础知识,以下将分析MySQL源码中,对红黑树的设计及实现过程进行详细分析。

       TREE相关的数据结构定义在MySQL源码的include/my_tree.hmysys/tree.c文件中,具体定义如下所示:

 

typedef struct st_tree_element {

  struct st_tree_element *left,*right;

  uint32 count:31,

        colour:1;                     /* black is marked as 1 */

} TREE_ELEMENT;

typedef struct st_tree {

  TREE_ELEMENT *root,null_element;

  TREE_ELEMENT **parents[MAX_TREE_HEIGHT];

  uint offset_to_key,elements_in_tree,size_of_element;

  ulong memory_limit, allocated;

  qsort_cmp2 compare;

  void *custom_arg;

  MEM_ROOT mem_root;

  my_bool with_delete;

  tree_element_free free;

  uint flag;

} TREE;

 

       TREE_ELEMENT数据结构中,定义了左右孩子结点指针leftright;结点的计数变量count31bit位),当红黑树允许相同结点存在时,该值表示该结点的计数值;结点的颜色变量colour1bit位),表示当前结点的颜色状态。

       TREE数据结构中,定义了根结点指针rootNIL结点null_elementparents指针数组,用于存储从根结点到当前结点所有的祖先结点,由于红黑树在结点旋转和颜色调整时,都会涉及到父节点;offset_to_key表示关键字的偏移量;elements_in_tree表示树中结点的数目;size_of_element表示每个对象存储的大小;memory_limit表示红黑树的内存限制;allocated表示已经分配的内存大小,当allocated大于memory_limit的值时,重置红黑树;compare比较函数指针,是键值的比较函数;custom_arg是比较函数的第一个参数;mem_rootMEM_ROOT数据结构,提供特别的内存分配的操作,详细分析参考《MySQL数据结构分析--MEM_ROOT[5]with_delete参数是用于控制使用mem_root内存分配方式,还是使用普通的内存分配方式;free释放内存函数指针,用于释放结点的内存空间;flag用于标志红黑树的一些特性,如TREE_NO_DUPS表示不允许红黑树中的元素重复。

源码实现

       根据数据结构定义可知,MySQL实现的红黑树不是用一个个的NIL结点表示,而用一个哨兵null_element来代替。结构设计如下所示,其中数字表示键值,仅仅是为了说明设计的结构,无实际的意义:

1 MySQL红黑树设计结构

 

       从操作来看,红黑树的基本操作包括插入、删除、查找等操作,内部实际处理操作包括旋转操作和颜色调整操作。具体如下:

tree_insert函数

       tree_insert()函数是红黑树插入新元素的操作,该处理过程首先按照二叉树的插入逻辑,将新节点插入到对应键值的位置。在查找插入位置时,将根结点root到查找位置路径上的结点的指针存储在parent指针数组中。实际的旋转和调整结点颜色处理逻辑在rb_insert()函数中,具体的处理逻辑参考该函数的详细分析过程。

tree_delete函数

       tree_delete()函数是红黑树删除元素的操作,首先处理过程同二叉树的删除逻辑类似,将删除结点左子树中最小的结点替换删除结点的位置。如果删除结点的颜色为红色,则不需要进行调整。否则,调用rb_delete_fixup()函数进行旋转和调整结点颜色,详细参考该函数的处理逻辑。

tree_search函数

       tree_search()函数是红黑树查找键值的操作,操作同二叉树查找逻辑一致。此外,MySQL提供了tree_search_key()tree_search_edge()tree_search_next()函数,提供进一步特殊的查询功能。

left_rotate函数

       left_rotate()函数是红黑树的左旋转函数,在rb_insert()rb_delete_fixup()函数调整红黑树平衡时,会根据红黑树结点的颜色和状态,调用该函数进行左旋转,已达到平衡。

right_rotate函数

       right_rotate()函数是红黑树的右旋转函数,处理过程类似left_rotate()函数。

rb_insert函数

       rb_insert()函数是红黑树插入元素后,进行旋转和颜色调整的主要处理过程,该过程根据parent中的父结点及其兄弟结点,以及插入的元素进行颜色调整和旋转操作。该过程分为3种不同的状态,具体不同状态的调整策略,同普通红黑树的调整一致。

rb_delete_fixup函数

       rb_delete_fixup()函数是红黑树删除元素后,对树进行旋转和颜色调整的主要处理过程。该过程分为四种不同状态,调整策略同普通红黑树的调整一致。

       其中,left_rotate()right_rotate()rb_insert()rb_delete_fixup()函数为内部函数,实现红黑树的旋转和颜色调整处理逻辑。

结论

       通过分析MySQL实现的红黑树数据结构TREE,发现TREE数据结构在原有红黑树基础上,进行了细微的改进和优化。具体如下

       1、使用哨兵null_element代替NIL结点,节省了内存空间;

       2、使用parent指针数组,记录从根结点到插入位置或删除元素位置的所有父结点,通过该指针数组,即可对红黑树进行旋转和颜色调整。从而避免了为每个元素定义parent指针,浪费内存空间;

       3、定义with_delete参数,使用MEM_ROOT数据结构内存分配方式,提高分配相同大小和类型的内存空间的效率。

 

参考资料

[1] 《算法导论第三版》 --P174-P192

[2] 《教你透彻了解红黑树》 --http://blog.csdn.net/v_JULY_v/article/details/6105630

[3] 《理解红黑树1 --http://blog.chinaunix.net/uid-26896862-id-3340352.html

[4] 《理解红黑树2 --http://blog.chinaunix.net/uid-26896862-id-3340353.html

[5] MySQL数据结构分析--MEM_ROOT --http://blog.chinaunix.net/uid-26896862-id-3412033.html

阅读(3138) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~