摘要:本文对B树索引的结构、内部管理等方面做了一个全面的介绍。同时深入探讨了一些与B树索引有关的广为流传的说法,比如删除记录对索引的影响,定期重建索引能解决许多性能问题等。

1.B树索引的相关概念

索引与表一样,也属于段(segment)的一种。里面存放了用户的数据,跟表一样需要占用磁盘空间。只

不过,在索引里的数据存放形式与表里的数据存放形式非常的不一样。在理解索引时,可以想象一本书,其中书的内容就相当于表里的数据,而书前面的目录就相当于该表的索引。同时,通常情况下,索引所占用的磁盘空间要比表要小的多,其主要作用是为了加快对数据的搜索速度,也可以用来保证数据的唯一性。

但是,索引作为一种可选的数据结构,你可以选择为某个表里的创建索引,也可以不创建。这是因为一旦创建了索引,就意味着oracle对表进行DML(包括INSERT、UPDATE、DELETE)时,必须处理额外的工作量(也就是对索引结构的维护)以及存储方面的开销。所以创建索引时,需要考虑创建索引所带来的查询性能方面的提高,与引起的额外的开销相比,是否值得。

从物理上说,索引通常可以分为:分区和非分区索引、常规B树索引、位图(bitmap)索引、翻转(reverse)索引等。其中,B树索引属于最常见的索引,由于我们的这篇文章主要就是对B树索引所做的探讨,因此下面只要说到索引,都是指B树索引。

B树索引是一个典型的树结构,其包含的组件主要是:

1)      叶子节点(Leaf node):包含条目直接指向表里的数据行。

2)      分支节点(Branch node):包含的条目指向索引里其他的分支节点或者是叶子节点。

3)      根节点(Root node):一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点。

可以用下图一来描述B树索引的结构。其中,B表示分支节点,而L表示叶子节点。

对于分支节点块(包括根节点块)来说,其所包含的索引条目都是按照顺序排列的(缺省是升序排列,也可以在创建索引时指定为降序排列)。每个索引条目(也可以叫做每条记录)都具有两个字段。第一个字段表示当前该分支节点块下面所链接的索引块中所包含的最小键值;第二个字段为四个字节,表示所链接的索引块的地址,该地址指向下面一个索引块。在一个分支节点块中所能容纳的记录行数由数据块大小以及索引键值的长度决定。比如从上图一可以看到,对于根节点块来说,包含三条记录,分别为(0 B1)、(500 B2)、(1000 B3),它们指向三个分支节点块。其中的0、500和1000分别表示这三个分支节点块所链接的键值的最小值。而B1、B2和B3则表示所指向的三个分支节点块的地址。

对于叶子节点块来说,其所包含的索引条目与分支节点一样,都是按照顺序排列的(缺省是升序排列,也可以在创建索引时指定为降序排列)。每个索引条目(也可以叫做每条记录)也具有两个字段。第一个字段表示索引的键值,对于单列索引来说是一个值;而对于多列索引来说则是多个值组合在一起的。第二个字段表示键值所对应的记录行的ROWID,该ROWID是记录行在表里的物理地址。如果索引是创建在非分区表上或者索引是分区表上的本地索引的话,则该ROWID占用6个字节;如果索引是创建在分区表上的全局索引的话,则该ROWID占用10个字节。

知道这些信息以后,我们可以举个例子来说明如何估算每个索引能够包含多少条目,以及对于表来说,所产生的索引大约多大。对于每个索引块来说,缺省的PCTFREE为10%,也就是说最多只能使用其中的90%。同时9i以后,这90%中也不可能用尽,只能使用其中的87%左右。也就是说,8KB的数据块中能够实际用来存放索引数据的空间大约为6488(8192×90%×88%)个字节。

假设我们有一个非分区表,表名为warecountd,其数据行数为130万行。该表中有一个列,列名为goodid,其类型为char(8),那么也就是说该goodid的长度为固定值:8。同时在该列上创建了一个B树索引。

在叶子节点中,每个索引条目都会在数据块中占一行空间。每一行用2到3个字节作为行头,行头用来存放标记以及锁定类型等信息。同时,在第一个表示索引的键值的字段中,每一个索引列都有1个字节表示数据长度,后面则是该列具体的值。那么对于本例来说,在叶子节点中的一行所包含的数据大致如下图二所示:

从上图可以看到,在本例的叶子节点中,一个索引条目占18个字节。同时我们知道8KB的数据块中真正可以用来存放索引条目的空间为6488字节,那么在本例中,一个数据块中大约可以放360(6488/18)个索引条目。而对于我们表中的130万条记录来说,则需要大约3611(1300000/360)个叶子节点块。

而对于分支节点里的一个条目(一行)来说,由于它只需保存所链接的其他索引块的地址即可,而不需要保存具体的数据行在哪里,因此它所占用的空间要比叶子节点要少。分支节点的一行中所存放的所链接的最小键值所需空间与上面所描述的叶子节点相同;而存放的索引块的地址只需要4个字节,比叶子节点中所存放的ROWID少了2个字节,少的这2个字节也就是ROWID中用来描述在数据块中的行号所需的空间。因此,本例中在分支节点中的一行所包含的数据大致如下图三所示:

从上图可以看到,在本例的分支节点中,一个索引条目占16个字节。根据上面叶子节点相同的方式,我们可以知道一个分支索引块可以存放大约405(6488/16)个索引条目。而对于我们所需要的3611个叶子节点来说,则总共需要大约9个分支索引块。

这样,我们就知道了我们的这个索引有2层,第一层为1个根节点,第二层为9个分支节点,而叶子节点数为3611个,所指向的表的行数为1300000行。但是要注意,在oracle的索引中,层级号是倒过来的,也就是说假设某个索引有N层,则根节点的层级号为N,而根节点下一层的分支节点的层级号为N-1,依此类推。对本例来说,9个分支节点所在的层级号为1,而根节点所在的层级号为2。

深入研究B树索引(一)的更多相关文章

  1. [MySQL] B+树索引

    B+树是一种经典的数据结构,由平衡树和二叉查找树结合产生,它是为磁盘或其它直接存取辅助设备而设计的一种平衡查找树,在B+树中,所有的记录节点都是按键值大小顺序存放在同一层的叶节点中,叶节点间用指针相连 ...

  2. 【转】 数据库系统——B+树索引

    原文来自于:http://blog.csdn.net/cjfeii/article/details/10858721 1. B+树索引概述 在上一篇文章中,我们讨论了关于index的几个中重要的课题: ...

  3. Oracle索引梳理系列(二)- Oracle索引种类及B树索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  4. MySQL:InnoDB存储引擎的B+树索引算法

    很早之前,就从学校的图书馆借了MySQL技术内幕,InnoDB存储引擎这本书,但一直草草阅读,做的笔记也有些凌乱,趁着现在大四了,课程稍微少了一点,整理一下笔记,按照专题写一些,加深一下印象,不枉读了 ...

  5. B+树索引和哈希索引的区别——我在想全文搜索引擎为啥不用hash索引而非得使用B+呢?

    哈希文件也称为散列文件,是利用哈希存储方式组织的文件,亦称为直接存取文件.它类似于哈希表,即根据文件中关键字的特点,设计一个哈希函数和处理冲突的方法,将记录哈希到存储设备上. 在哈希文件中,是使用一个 ...

  6. Hash索引和B树索引

    要知道磁盘结构优化访问的关键在于以block为单位(比如每次读取一个页面) 这两种索引差别也就在聚集到一个block的标准: B树聚集到一个block是因为关键字在一个范围内,关键字在block内的排 ...

  7. 浅谈B+树索引的分裂优化(转)

    http://www.tamabc.com/article/85038.html 从MySQL Bug#67718浅谈B+树索引的分裂优化   原文链接:http://hedengcheng.com/ ...

  8. B树索引和位图索引的区别!

    B树索引主键和唯一性约束字段的B树索引,效率几乎和海量数据没有关系. 键值重复率低的字段比较适合使用B树索引. 位图索引键值重复率高的字段比较适合使用位图索引.count.and.or.in这些特定的 ...

  9. MySQL B+树索引和哈希索引的区别

      导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BT ...

随机推荐

  1. (转) mac 下的eclipse 配置 python 2.7

    原地址: http://marsfreewill.blogspot.it/2012/08/mac-ospythonpydeveclipse.html   在MAC OS上配置Python开发环境(Py ...

  2. 用Apache Ivy实现项目里的依赖管理

    Apache Ivy是一个管理项目依赖的工具. 它与Maven  Apache Maven 构建管理和项目管理工具已经吸引了 Java 开发人员的注意.Maven 引入了 JAR 文件公共存储库的概念 ...

  3. 使用xml及java代码混合的方式来设置图形界面

    参考<疯狂android讲义>第2版2.1节 设置android的图形界面有三种方法: 1.使用纯xml文件 2.使用纯java,代码臃肿复杂,不建议使用 3.使用xml与java混合,前 ...

  4. CSS浏览器兼容问题集-第一部分

    CSS对浏览器的兼 容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理方法并整理了一下.对于 web2.0的过度,请尽量用xhtm ...

  5. Spring HibernateTemplate的使用

    Spring HibernateTemplate的使用 2008-03-25 11:38 2020人阅读 评论(0) 收藏 举报 springbeanhibernatesessiondaoclass ...

  6. H5本地存储

    在HTML5中可以把数据长期存储在客户端,使用的对象就是localStorage. localStorage常用方法有setItem.getItem.removeItem.clear. 下面是一个存储 ...

  7. 【Python学习】由于windows环境问题导致的不能安装某些需要VC编译的插件

    由于windows环境问题导致的不能安装某些需要VC编译的插件 下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 安装方法: 在CMD中输入 pip in ...

  8. basename $0的用法

    basename 从文件名中去掉路径信息, 只打印出文件名. 结构 basename $0 可以让脚本知道它自己的名字, 也就是, 它被调用的名字. 可以用来显示用法信息, 比如如果你调用脚本的时候缺 ...

  9. STM32之------独立看门狗(IWDG)和窗体看门狗(WWDG)

    一     前沿废语: 之前有很风靡的游戏,名字叫<看门狗>.该游戏用了很新的引擎技术,打造出了一个辽阔庞大的世界,内容是玩家Aiden·Pearce(主角)是一名精通黑客技术的高手,当时 ...

  10. spring3.0事务的配置

    第一种配置方法:基于XML的事务管理 这种方法不需要对原有的业务做任何修改,通过在XML文件中定义需要拦截方法的匹配即可完成配置,要求是,业务处理中的方法的命名要有规律,比如setXxx,xxxUpd ...