首先我们介绍一下一?m 阶B-tree的特性,那么q个 m 阶是怎么定义的呢Q这里我们以一个节点能拥有的最大子节点数来表示q颗树的阶数。D个例子,如果一个节Ҏ多有 n 个keyQ那么这个节Ҏ多就会有 n+1 个子节点Q这|叫?n+1Qm=n+1Q阶树。一?m 阶B-tree包括以下5条特性:
q些Ҏ可能看着不太好理解,下面我们会介lB-tree的插入,在插入节点的q程中我们就会慢慢理解这些特性了。B-tree的插入比较简单,是一个节点至下而上的分裂过E。下面我们具体以一?阶树来展CB-tree的插入过E?/p>
首先我们 插入 200Q?00Q?00Q没有什么问题,直接插入好?/p>
| 200 | 300 | 400 |
现在我们接着插入500Q这个时候我们发现有炚w题,Ҏ定义及特?我们知道一?阶B-tree的每个节Ҏ多只能有3个keyQ插?00后这个节点就?个key了?/p>
| 200 | 300 | 400 | 500 |
q个时候我们就需要分裂,中间的key上移到父节点Q左边的作ؓ左节点,双的作为右节点Q如下图所C:
通过整个的插入过E我们也会发玎ͼB-tree和二叉树的一个显著的区别是QB-tree是从下往上生长,而二叉树是从上往下生长的。现在我们想想特?和特?是ؓ什么?首先我们知道子节点的个数是等于key的数?1Q然后一个节点达到m个key后就会分裂,所以分裂后的节Ҏ能得到 m/2 - 1个key 。ؓ啥还要减一呢?因ؓq要拿一个作为父节点。所以这个节Ҏ回拥有 m/2 - 1 + 1 = m/2 个子节点。同样得到特?Q因为最有m/2个子节点Q所以最就含有m/2-1个keyQm 阶树Q每个节点存Cm个key׃分裂Q所以最多就?m-1个key?/p>
Ҏ以上Ҏ我们能推出一含有N个d键字数的m阶的B-tree树的最大高度h的?
树的高度h: 1Q?2Q?3 Q?4 Q?......... Q?h
节点个数s: 1Q?2Q?2*(m/2)Q?2*(m/2)(m/2)Q?........ Q?*(m/2)的h-2ơ方
s = 1 + 2(1 - )/(1- (m/2))
N = 1 + s * ((m/2) - 1) = 2 * ( ) - 1
h = log┌m/2┐((N+1)/2 )+1
2Qؓ什么btree/b+tree 为常用数据库索引l构Q?br />
上文说过Q红黑树{数据结构也可以用来实现索引Q但是文件系l及数据库系l普遍采用B-/+Tree作ؓ索引l构Q这一节将l合计算机组成原理相关知识讨论B-/+Tree作ؓ索引的理论基?/p>
一般来_索引本n也很大,不可能全部存储在内存中,因此索引往往以烦引文件的形式存储的磁盘上。这L话,索引查找q程中就要生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量Q所以评价一个数据结构作为烦引的优劣最重要的指标就是在查找q程中磁盘I/O操作ơ数的渐q复杂度。换句话_索引的结构组l要量减少查找q程中磁盘I/O的存取次数。下面先介绍内存和磁盘存取原理,然后再结合这些原理分析B-/+Tree作ؓ索引的效率?/p>
目前计算Z用的d基本都是随机d存储器(RAMQ,CRAM的结构和存取原理比较复杂Q这里本文抛却具体差别,抽象Z个十分简单的存取模型来说明RAM的工作原理?/p>
?
从抽象角度看Q主存是一pd的存储单元组成的矩阵Q每个存储单元存储固定大的数据。每个存储单元有唯一的地址Q现代主存的~址规则比较复杂Q这里将其简化成一个二l地址Q通过一个行地址和一个列地址可以唯一定位C个存储单元。图5展示了一? x 4的主存模型?/p>
d的存取过E如下:
当系l需要读取主存时Q则地址信号攑ֈ地址ȝ上传l主存,dd地址信号后,解析信号q定位到指定存储单元Q然后将此存储单元数据放到数据ȝ上,供其它部件读取?/p>
写主存的q程cMQ系l将要写入单元地址和数据分别放在地址ȝ和数据ȝ上,dd两个ȝ的内容,做相应的写操作?/p>
q里可以看出Q主存存取的旉仅与存取ơ数呈线性关p,因ؓ不存在机械操作,两次存取的数据的“距离”不会Ҏ间有M影响Q例如,先取A0再取A1和先取A0再取D3的时间消耗是一L?/p>
上文说过Q烦引一般以文g形式存储在磁盘上Q烦引检索需要磁盘I/O操作。与d不同Q磁盘I/O存在机械q动耗费Q因此磁盘I/O的时间消耗是巨大的?/p>
?是磁盘的整体l构C意图?/p>
?
一个磁盘由大小相同且同轴的圆Ş盘片l成Q磁盘可以{动(各个盘必须同步转动Q。在盘的一侧有头支架Q磁头支架固定了一l磁_每个头负责存取一个磁盘的内容。磁头不能{动,但是可以沿磁盘半径方向运动(实际是斜切向q动Q,每个头同一时刻也必L同u的,即从正上方向下看Q所有磁头Q何时候都是重叠的Q不q目前已l有多磁头独立技术,可不受此限制Q?/p>
?是磁盘结构的C意图?/p>
?
盘片被划分成一pd同心环,圆心是盘片中心,每个同心环叫做一个磁道,所有半径相同的道l成一个柱面。磁道被沿半径线划分成一个个的D,每个D叫做一个扇区,每个扇区是磁盘的最存储单元。ؓ了简单v见,我们下面假设盘只有一个盘片和一个磁头?/p>
当需要从盘d数据Ӟpȝ会将数据逻辑地址传给盘Q磁盘的控制电\按照d逻辑逻辑地址译成物理地址Q即定要读的数据在哪个道Q哪个扇区。ؓ了读取这个扇区的数据Q需要将头攑ֈq个扇区上方Qؓ了实现这一点,头需要移动对准相应磁道,q个q程叫做寻道Q所耗费旉叫做寻道旉Q然后磁盘旋转将目标扇区旋{到磁头下Q这个过E耗费的时间叫做旋转时间?/p>
׃存储介质的特性,盘本n存取比d慢很多,再加上机械运动耗费Q磁盘的存取速度往往是主存的几百分分之一Q因此ؓ了提高效率,要尽量减磁盘I/O。ؓ了达到这个目的,盘往往不是严格按需dQ而是每次都会预读Q即使只需要一个字节,盘也会从这个位|开始,序向后d一定长度的数据攑օ内存。这样做的理Z据是计算机科学中著名的局部性原理:
当一个数据被用到Ӟ光q的数据也通常会马上被使用?/p>
E序q行期间所需要的数据通常比较集中?/p>
׃盘序d的效率很高(不需要寻道时_只需很少的旋转时_Q因此对于具有局部性的E序来说Q预d以提高I/O效率?/p>
预读的长度一般ؓ(pageQ的整倍数。页是计机理存储器的逻辑块,g及操作系l往往主存和盘存储区分割ؓq箋的大相{的块,每个存储块称Z(在许多操作系l中Q页得大通常?kQ,d和磁盘以ؓ单位交换数据。当E序要读取的数据不在d中时Q会触发一个缺异常,此时pȝ会向盘发出ȝ信号Q磁盘会扑ֈ数据的v始位|ƈ向后q箋d一|几页载入内存中,然后异常q回Q程序l运行?/p>
到这里终于可以分析B-/+Tree索引的性能了?/p>
上文说过一般用磁盘I/Oơ数评h索引l构的优劣。先从B-Tree分析Q根据B-Tree的定义,可知索一ơ最多需要访问h个节炏V数据库pȝ的设计者y妙利用了盘预读原理Q将一个节点的大小设ؓ{于一个页Q这h个节点只需要一ơI/O可以完全蝲入。ؓ了达到这个目的,在实际实现B- Treeq需要用如下技巧:
每次新徏节点Ӟ直接甌一个页的空_q样׃证一个节点物理上也存储在一个页里,加之计算机存储分配都是按对齐的Q就实现了一个node只需一ơI/O?/p>
B-Tree中一ơ检索最多需要h-1ơI/OQ根节点帔R内存Q,渐进复杂度ؓO(h)=O(logdN)?/strong>一般实际应用中Q出度d是非常大的数字,通常过100Q因此h非常(通常不超q?Q?/p> lg所qͼ用B-Tree作ؓ索引l构效率是非帔R的?/p> 而红黑树q种l构Qh明显要深的多。由于逻辑上很q的节点Q父子)物理上可能很q,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h)Q效率明显比B-Tree差很多?/p> 上文q说q,B+Tree更适合外存索引Q原因和内节点出度d有关。从上面分析可以看到Qd大索引的性能好Q而出度的上限取决于节点内key和data的大: dmax = floor(pagesize / (keysize + datasize + pointsize)) (pagesize – dmax >= pointsize) ?/p> dmax = floor(pagesize / (keysize + datasize + pointsize)) - 1 (pagesize – dmax < pointsize) floor表示向下取整。由于B+Tree内节点去掉了data域,因此可以拥有更大的出度,拥有更好的性能?/p> q一章从理论角度讨论了与索引相关的数据结构与法问题Q下一章将讨论B+Tree是如何具体实CؓMySQL中烦引,同时结合MyISAM和InnDB存储引擎介绍非聚集烦引和聚集索引两种不同的烦引实现Ş式?/p>
]]>