- 浏览: 29521 次
- 性别:
- 来自: 广州
最新评论
5. 重建 B 树索引
5.1 如何重建 B 树索引
重建索引有两种方法:一种是最简单的,删除原索引,然后重建;第二种是使用 ALTER INDEX … REBUILD
命令对索引进行重建。第二种方式是从 oracle 7.3.3 版本开始引入的,从而使得用户在重建索引时不必删除原索引再重新 CREATE INDEX 了。 ALTER INDEX … REBUILD 相对 CREATE INDEX 有以下好处:
1) 它使用原索引的叶子节点作为新索引的数据来源。我们知道,原索引的叶子节点的数据块通常都要比表里的数据块要少很多,因此进行的 I/O 就会减少;同时,由于原索引的叶子节点里的索引条目已经排序了,因此在重建索引的过程中,所做的排序工作也要少的多。
2) 自从 oracle 8.1.6 以来, ALTER INDEX … REBUILD 命令可以添加 ONLINE 短语。这使得在重建索引的过程中,用户可以继续对原来的索引进行修改,也就是说可以继续对表进行 DML 操作。
而同时, ALTER INDEX … REBUILD 与 CREATE INDEX 也有很多相同之处:
1) 它们都可以通过添加 PARALLEL 提示进行并行处理。
2) 它们都可以通过添加 NOLOGGING 短语,使得重建索引的过程中产生最少的重做条目( redo entry )。
3) 自从 oracle 8.1.5 以来,它们都可以田间 COMPUTE STATISTICS 短语,从而在重建索引的过程中,就生成 CBO 所需要的统计信息,这样就避免了索引创建完毕以后再次运行 analyze 或 dbms_stats 来收集统计信息。
当我们重建索引以后,在物理上所能获得的好处就是能够减少索引所占的空间大小(特别是能够减少叶子
节点的数量)。而索引大小减小以后,又能带来以下若干好处:
1) CBO 对于索引的使用可能会产生一个较小的成本值,从而在执行计划中选择使用索引。
2) 使用索引扫描的查询扫描的物理索引块会减少,从而提高效率。
3) 由于需要缓存的索引块减少了,从而让出了内存以供其他组件使用。
尽管重建索引具有一定的好处,但是盲目的认为重建索引能够解决很多问题也是不正确的。比如我见过一
个生产系统,每隔一个月就要重建所有的索引(而且我相信,很多生产系统可能都会这么做),其中包括一些 100GB 的大表。为了完成重建所有的索引,往往需要把这些工作分散到多个晚上进行。事实上,这是一个 7 × 24 的系统,仅重建索引一项任务就消耗了非常多的系统资源。但是每隔一段时间就重建索引有意义吗?这里就有一些关于重建索引的很流行的说法,主要包括:
1) 如果索引的层级超过 X ( X 通常是 3 )级以后需要通过重建索引来降低其级别。
2) 如果经常删除索引键值,则需要定时重建索引来收回这些被删除的空间。
3) 如果索引的 clustering_factor 很高,则需要重建索引来降低该值。
4) 定期重建索引能够提高性能。
对于第一点来说,我们在前面已经知道, B 树索引是一棵在高度上平衡的树,所以重建索引基本不可能降
低其级别,除非是极特殊的情况导致该索引有非常大量的碎片,导致 B 树索引“虚高”,那么这实际又来到第二点上(因为碎片通常都是由于删除引起的)。实际上,对于第一和第二点,我们应该通过运行 ALTER INDEX … REBUILD 命令以后检查 indest_stats.pct_used 字段来判断是否有必要重建索引。
5.2 重建 B 树索引对于 clustering_factor 的影响
而对于 clustering_factor 来说,它是用来比较索引的顺序程度与表的杂乱排序程度的一个度量。 Oracle 在计算某个 clustering_factor 时,会对每个索引键值查找对应到表的数据,在查找的过程中,会跟踪从一个表的数据块跳转到另外一个数据块的次数(当然,它不可能真的这么做,源代码里只是简单的扫描索引,从而获得 ROWID ,然后从这些 ROWID 获得表的数据块的地址)。每一次跳转时,有个计数器就会增加,最终该计数器的值就是 clustering_factor 。下图四描述了这个原理。
图四
在上图四中,我们有一个表,该表有 4 个数据块,以及 20 条记录。在列 N1 上有一个索引,上图中的每个小黑点就表示一个索引条目。列 N1 的值如图所示。而 N1 的索引的叶子节点包含的值为: A 、 B 、 C 、 D 、 E 、 F 。如果 oracle 开始扫描索引的底部,叶子节点包含的第一个 N1 值为 A ,那么根据该值可以知道对应的 ROWID 位于第一个数据块的第三行里,所以我们的计数器增加 1 。同时, A 值还对应第二个数据块的第四行,由于跳转到了不同的数据块上,所以计数器再加 1 。同样的,在处理 B 时,可以知道对应第一个数据块的第二行,由于我们从第二个数据块跳转到了第一个数据块,所以计数器再加 1 。同时, B 值还对应了第一个数据块的第五行,由于我们这里没有发生跳转,所以计数器不用加 1 。
在上面的图里,在表的每一行的下面都放了一个数字,它用来显示计数器跳转到该行时对应的值。当我们处理完索引的最后一个值时,我们在数据块上一共跳转了十次,所以该索引的 clustering_factor 为 10 。
注意第二个数据块, clustering_factor 为 8 出现了 4 次。因为在索引里 N1 为 E 所对应的 4 个索引条目都指向了同一个数据块。从而使得 clustering_factor 不再增长。同样的现象出现在第三个数据块中,它包含三条记录,它们的值都是 C ,对应的 clustering_factor 都是 6 。
从 clustering_factor 的计算方法上可以看出,我们可以知道它的最小值就等于表所含有的数据块的数量;而最大值就是表所含有的记录的总行数。很明显, clustering_factor 越小越好,越小说明通过索引查找表里的数据行时需要访问的表的数据块越少。
我们来看一个例子,来说明重建索引对于减小 clustering_factor 没有用处。首先我们创建一个测试表:
SQL> create table clustfact_test(id number,name varchar2(10)); SQL> create index idx_clustfact_test on clustfact_test(id);
然后,我们插入十万条记录。
SQL> begin 2 for i in 1..100000 loop 3 insert into clustfact_test values(mod(i,200),to_char(i)); 4 end loop; 5 commit; 6 end; 7 /
因为使用了 mod 的关系,最终数据在表里排列的形式为:
0,1,2,3,4,5,…,197,198,199,0,1,2,3,…, 197,198,199,0,1,2,3,…, 197,198,199,0,1,2,3,…
接下来,我们分析表。
SQL> exec dbms_stats.gather_table_stats(user,'clustfact_test',cascade=>true);
这个时候,我们来看看该索引的 clustering_factor 。
SQL> select num_rows, blocks from user_tables where table_name = 'CLUSTFACT_TEST'; NUM_ROWS BLOCKS ---------- ---------- 100000 202 SQL> select num_rows, distinct_keys, avg_leaf_blocks_per_key, avg_data_blocks_per_key, 2 clustering_factor from user_indexes where index_name = 'IDX_CLUSTFACT_TEST'; NUM_ROWS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR ---------- ------------- ----------------------- ----------------------- ----------------- 100000 200 1 198 39613
从上面的 avg_data_blocks_per_key 的值为 198 可以知道,每个键值平均分布在 198 个数据块里,而整个表也就 202 个数据块。这也就是说,要获取某个键值的所有记录,几乎每次都需要访问所有的数据块。从这里已经可以猜测到 clustering_factor 会非常大。事实上,该值近 4 万,也说明该索引并不会很有效。
我们来看看下面这句 SQL 语句的执行计划。
SQL> select count(name) from clufac_test where id = 100; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=32 Card=1 Bytes=9) 1 0 SORT (AGGREGATE) 2 1 TABLE ACCESS (FULL) OF 'CLUFAC_TEST' (Cost=32 Card=500 Bytes=4500) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 205 consistent gets ……
很明显, CBO 弃用了索引,而使用了全表扫描。这实际上已经说明由于索引的 clustering_factor 过高,导致通过索引获取数据时跳转的数据块过多,成本过高,因此直接使用全表扫描的成本会更低。
这时我们来重建索引看看会对 clustering_factor 产生什么影响。从下面的测试中可以看到,没有任何影响。
SQL> alter index idx_clustfact_test rebuild; SQL> select num_rows, distinct_keys, avg_leaf_blocks_per_key, avg_data_blocks_per_key, 2 clustering_factor from user_indexes where index_name = 'IDX_CLUSTFACT_TEST'; NUM_ROWS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR ---------- ------------- ----------------------- ----------------------- ----------------- 100000 200 1 198 39613
那么当我们将表里的数据按照 id 的顺序(也就是索引的排列顺序)重建时,该 SQL 语句会如何执行?
SQL> create table clustfact_test_temp as select * from clustfact_test order by id; SQL> truncate table clustfact_test; SQL> insert into clustfact_test select * from clustfact_test_temp; SQL> exec dbms_stats.gather_table_stats(user,'clustfact_test',cascade=>true); SQL> select num_rows, distinct_keys, avg_leaf_blocks_per_key, avg_data_blocks_per_key, 2 clustering_factor from user_indexes where index_name = 'IDX_CLUSTFACT_TEST'; NUM_ROWS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR ---------- ------------- ----------------------- ----------------------- ----------------- 100000 200 1 1 198
很明显的,这时的索引里每个键值只分布在 1 个数据块里,同时 clustering_factor 也已经降低到了 198 。这时再次执行相同的查询语句时, CBO 将会选择索引,同时可以看到 consistent gets 也从 205 降到了 5 。
SQL> select count(name) from clustfact_test where id = 100; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=1 Bytes=9) 1 0 SORT (AGGREGATE) 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'CLUSTFACT_TEST' (Cost=2 Card=500 Bytes=4500) 3 2 INDEX (RANGE SCAN) OF 'IDX_CLUSTFACT_TEST' (NON-UNIQUE) (Cost=1 Card=500) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 5 consistent gets ……
所以我们可以得出结论,如果仅仅是为了降低索引的 clustering_factor 而重建索引没有任何意义。降低 clustering_factor 的关键在于重建表里的数据。只有将表里的数据按照索引列排序以后,才能切实有效的降低 clustering_factor 。但是如果某个表存在多个索引的时候,需要仔细决定应该选择哪一个索引列来重建表。
发表评论
-
(转)Andriod是什么
2010-12-02 11:24 1611导读:Sans Serif是Google的 ... -
(转)SQLite入门与分析(六)---再谈SQLite的锁
2010-11-19 00:09 941写在前 面:SQLite封锁机制的实现需要底层文件系统的 ... -
(转)SQLite入门与分析(五)---Page Cache之并发控制
2010-11-19 00:05 1045写在前面:本节主要谈 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(3)
2010-11-19 00:01 949Code 写在前面:由于 内容较多,所以断续没有写完的 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(2)
2010-11-18 23:57 1140写在前面:个人认为pager层是SQLite实现最为核心的 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(1)
2010-11-18 23:53 938写在前面:从本章开始,将对SQLite的每个模块进行讨论。 ... -
(转)SQLite入门与分析(三)---内核概述(2)
2010-11-18 23:48 1300写在前面:本节 是前 ... -
(转)SQLite入门与分析(三)---内核概述(1)
2010-11-18 23:41 794写在前面:从本 章开始, ... -
(转)SQLite入门与分析(二)---设计与概念(续)
2010-11-18 23:38 1039写在前面:本节 讨论事务,事务是DBMS最核心的技术之一 ... -
(转)SQLite入门与分析(二)---设计与概念
2010-11-18 23:35 789写在前面:谢谢各位的 ... -
(转)SQLite入门与分析(一)
2010-11-18 23:31 904写在前面:出于项目的 需要,最近打算对SQLite的内核 ... -
(转)深入研究B树索引(五)续
2010-11-18 15:10 9245.3 重建 B 树索引 ... -
(转)深入研究B树索引(四)续
2010-11-18 14:58 9114.2 B 树索引的对于删除( DEL ... -
(转)深入研究B树索引(三、四)
2010-11-18 14:44 7113. B 树索 ... -
(转)深入研究B树索引(二)
2010-11-18 14:20 7562. B 树索引的内部结构 ... -
(转)深入研究B树索引(一)
2010-11-18 14:12 1000摘要: 本文对B 树索引的结构、内部管理等方面做了一个全面 ... -
(转)B树、B-树、B+树、B*树都是什么
2010-11-17 23:46 671B 树 即二叉搜 ... -
画UML图时注意的几个原则(转)
2010-08-03 12:34 1622软件开发中,分析和设计时,文档的编写和思想的交流,经常要绘制各 ... -
你是个软件架构师吗?(转)
2010-07-14 11:11 661开发和架构的界限难以 ... -
(转)同曲异奏——高效能项目团队的五大特点
2010-03-29 00:24 856同曲异奏——高效能项 ...
相关推荐
**深入研究B树索引** B树(B-tree)是一种自平衡的树数据结构,广泛应用于数据库和文件系统中,特别是在实现索引存储时。它能够保持数据有序,允许快速查找、插入和删除操作。本篇文章将深入探讨B树的核心概念、...
B树索引是一种高效的数据检索方法,广泛应用于数据库系统中,特别是关系型数据库管理系统。B树索引的主要目的是加速数据的查找、排序和更新操作,通过构建一种平衡的多路搜索树结构,使得数据访问更加高效。 B树...
总的来说,B树索引和自创Connect都是为了提升数据检索的效率。理解它们的原理和特点,有助于我们设计更高效的数据库系统,并在实际项目中选择最适合的数据结构。通过源码分享,我们可以深入研究这些数据结构的实现,...
3. B+树索引结构:B+树是一种广泛使用的树形结构数据索引方式,是B树的一种变种,特别适合用于磁盘存储。它能够有效地组织大量数据,并支持快速的查找、顺序访问、插入和删除操作。在数据库系统中,B+树被广泛用作...
B*树(B-star tree)是B树的一个变种,它在B树的基础上进行了优化,以适应大规模数据存储和高效查询的需求。 B*树索引的核心特点在于它的分层结构,每个节点可以包含多个子节点,并且每个节点可以存储多个键值和...
磁盘数据页存储结构是数据库管理中的一项关键...在深入研究索引和查询原理之前,理解数据页的存储结构是必不可少的。只有这样,我们才能更好地掌握数据库系统的内部工作机制,进而设计出更优的索引和执行更高效的查询。
cpp-DeepDataBase是一个使用B树索引实现的关系数据库引擎,它的设计目标是提供一个轻量级、高效的数据库解决方案。DeepDataBase是用C++编程语言编写的,这意味着它利用了面向对象的特性,同时保持了较低级别的性能...
在IT领域,数据结构是计算机科学中的核心概念之一,它为高效地存储和处理数据提供了理论基础。...对这些文件进行深入研究,不仅可以了解B+树索引的实现,还可以进一步提升C语言编程和数据结构理解的能力。
R树是由Guttman在1984年提出的一种多维索引结构,它是对B树的扩展,用于存储和查询具有空间属性的数据。R树的主要目标是在多维空间中有效地组织和检索数据,通过构建一种平衡的树形结构来降低搜索成本。 在R树中,...
通过对这些文件的研究,我们可以深入理解C语言和B树在实际问题中的应用,提升编程和数据结构设计的能力。 总的来说,C语言数据结构中的B树在图书管理系统中的应用,既展示了数据结构理论的实际价值,也锻炼了编程和...
B-树实际上是B树的一个变种,通常在数据库索引中较少提及,更多是在学术研究领域讨论。 **特点:** - 具有相同的关键字数量,但比B树少一个子节点; - 在每个节点中,关键字的数量等于子节点的数量减一; - 每个...
为了更好地理解这些数据结构,可以先从B-树入手,熟悉其基本原理和操作流程,然后再研究B+树的差异。项目提供的源代码可以作为实践平台,通过阅读和调试代码,加深对B-树和B+树的理解。 总结来说,这个C++实现的B-...
文章通过对B+树数据库索引结构的分析,研究了其关系表,并评估了B+树的索引效果。在此基础上,设计了电力大数据混合索引的结构,并对其性能进行了深入分析。 在索引设计过程中,电力大数据的特征和规律被充分考虑,...
在关系数据库管理系统中,B+树索引是提高查询性能的关键技术。索引的构建和维护是数据库管理的重要组成部分,它需要在保证数据一致性的同时,提供高效的查询和更新操作。通过Java实现B+树算法,不仅可以优化数据库...
总结,这个压缩包提供了一个学习和研究B+树的良好平台,对于理解数据结构和算法,以及提高C语言编程技能都非常有价值。通过分析和实践其中的代码,你可以掌握B+树的基本操作,并了解到如何在实际项目中优化数据访问...
通过深入研究和应用如QR2树索引等创新方法,可以显著提升空间数据库的性能,满足日益增长的大数据处理需求。随着技术的不断进步,未来空间数据库索引技术将继续发展,为地理信息科学、城市规划、自然资源管理等领域...
**B树(B-tree)**是一种自平衡的查找树数据结构,它能够保持数据排序,适合用于数据库和文件系统等领域。...对于给定的压缩文件“bplustree”,可能包含了B树或B+树的示例代码和相关工具,供学习者深入研究和实践。