oracle b树索引原理,简单说说B+树索引的结构和原理

本文介绍了B+树索引的基本原理,特别关注Oracle数据库的B树索引结构,包括枝节点和叶节点的特性。通过实例展示了索引的工作方式,如范围扫描和排序操作,并提及了PostgreSQL索引的相似性和差异,特别是其额外的bitmap字段用于处理NULL值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天PG社区在讨论B树索引的结构(这里B树是一个泛泛的称呼,搞数学的人要严谨,应该说是B+树。老白翻了翻以前写过的一些资料,整理一下,和大家分享。一般数据库的索引都使用B+树结构,这是一种变种的B树结构。和B树相同的是一个节点内可以有多个指针(不同于二叉树),不同的是B+树的枝节点里面没有数据,只有叶节点中有数据。在BLOCK SIZE相同的情况下,这种结构有助于用更少的枝块来构建一棵平衡的树,让树的层次尽可能的小。B+树结构是1972年被发明的,一经出现就成为数据库索引的首选。

faf484886e2cfbf937def6affe261058.png上面这张图来自于首发B+树的那篇论文。分支节点只做索引,只有叶节点存储数据。索引键左侧的块都小于索引键值,右侧的都大于索引键值。今天老白以Oracle的B树索引为例,来分析一下索引的结构。实际上在老白的《DBA的思想天空》中就讨论过索引的结构,B树索引是一棵带双向叶节点链的B+树,如下图:

7fce754d3d34f9c0f79bcf4548881288.png

图1我们可以用一个实际的例子来看一棵索引树的结构(老白创建了一个索引,然后用treedump事件把索引的结构DUMP出来)

cf8d96c49c31bff899be2c1f0d6b54d1.png

图2这个TREEDUMP中,我们可以看出一共有16个索引块,其中一个枝节点,带有15个指针,指向15个页块。整个索引一共只有2层。我们来看看枝节点的结构。

e0a53590fa1f1350b58efa2b87fa2bcf.png

通过Oracle的工具我们计算出枝节点的文件号和块号,然后DUMP出来:

656480bc7a213e7b60bcce0d2e14caef.png这里我们看到只有14条记录,和上面的15条似乎有点对不上,大家可以看到每个level都是从-1开始编码的,小于最小那个键值的就是-1号块,不需要一个指针了,这样可以节约一个指针。从这里可以看出Oracle在设计上处处都透着节约。我们下面来看一个叶节点块。

8b7a47e36911be36deb05b156116bad9.png

75a8ce0abcfe2f27eb967e0a602c57ce.png大家注意3的位置就是键值,COL0,4的位置COL1就是该键值对应的数据表的ROWID,通过这个ROW就可以找到这条记录了。大家注意下1和2,这就是叶节点双向链表。大家可以看到,kdxlenxt是下一个叶节点,而Kdxleprv是前一个叶节点。具体大家可以对照图2的数据。叶节点链使扫描变得更为高效。只要找到第一条符合条件的记录,如果使>=操作,就顺着叶节点链往高查找,直到不满足条件为止。如果使

4a367fa5006bc3eab77c50de5f21c05c.png这是一个一级枝节点,一级叶节点的索引。id>=100的数据指向208,200的指向209,以此类推。这里有一个207块,就是-1号节点,存储小于100的数据。我们来看看索引是如何工作的。select ... from ... where id=100

8f69e2879a52493299ef456d72b97e2b.png

索引范围扫描(如果是主键就是索引唯一性扫描)select ... from ... where id<100

d54b5e987234da961a9695864f76fe3a.png

索引范围扫描select ... from ... where id>100 and id<300

4362512ebc60cea1c9d0e77de6a4f1ae.png

索引范围扫描select id from ...  order by id

6e7e814320351b7fd022d32aa7be93a9.png

全索引扫描select id from ... order by id desc

33900f771ad29888b1152e88c206e35d.png

全索引扫描select id from ...

dac746d8b7cccee87393385088cb1adc.png

快速索引扫描

最后我们谈谈Postgresql的索引,实际上虽然实现方式有些差异,Postgresql的索引结构和ORACLE十分类似。下面的论述来自于老白查阅的Pat Shaughnessy 在20,000 Leagues Under ActiveRecord大会上的演讲稿。包括截图都是,并不是老白自己研究的结果。分享出来只是为了让大家更好的理解PG的索引结构。

6821e006394620d4a61968ac8e1e421d.png

PG的索引多了一个bitmap字段,这个字段是用来指示键值中是否包含NULL。

t_tid是指向一个元组的指针。而t_info包含一些统计值,包括有多少个值以及是否包含NULL等。下面的例子更为直观:

b622fab6e1a1b3221dba625aa54ba7fb.png

今天的内容就到这里。PG的源码注释写的相当完善,对PG索引有兴趣深入研究的朋友可以去阅读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值