B tree索引学习总结

b tree索引

索引的结构:
1.创建一个测试表
create table it
(x number ,y varchar2(100));

2.插入一万行数据

begin
for i in 1..100000
loop
insert into it values(i,rpad(i,100,‘*‘));
end loop;
end;
/

3.创建索引在x列上

create index idx_it on it(x);

4.收集表信息

SQL> exec dbms_stats.gather_table_stats(user,‘IT‘,cascade=>TRUE);

PL/SQL procedure successfully completed

5.将脏块写入文件
alter system flush buffer_cache;

6.查出表it的object_id

SQL> select object_id from dba_objects where object_name=‘IDX_IT‘;

OBJECT_ID
----------
86433

7.dump出整个索引结构
SQL> alter session set events ‘immediate trace name treedump level 86433‘;

Session altered.

SQL> select * from v$diag_info where name=‘Default Trace File‘;

INST_ID NAME
---------- ----------------------------------------------------------------
VALUE
--------------------------------------------------------------------------------
1 Default Trace File
/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_5816.trc

8.vi部分dump文件
----- begin tree dump
branch: 0x1016403 16868355 (0: nrow: 222, level: 1)
leaf: 0x1016404 16868356 (-1: nrow: 485 rrow: 485)
leaf: 0x1016405 16868357 (0: nrow: 479 rrow: 479)
leaf: 0x1016406 16868358 (1: nrow: 479 rrow: 479)
leaf: 0x1016407 16868359 (2: nrow: 479 rrow: 479)
leaf: 0x1016408 16868360 (3: nrow: 479 rrow: 479)
leaf: 0x1016409 16868361 (4: nrow: 478 rrow: 478)
leaf: 0x101640a 16868362 (5: nrow: 479 rrow: 479)
leaf: 0x101640b 16868363 (6: nrow: 479 rrow: 479)
leaf: 0x101640c 16868364 (7: nrow: 479 rrow: 479)
leaf: 0x101640d 16868365 (8: nrow: 478 rrow: 478)
leaf: 0x101640e 16868366 (9: nrow: 479 rrow: 479)
leaf: 0x101640f 16868367 (10: nrow: 479 rrow: 479)
leaf: 0x1016411 16868369 (11: nrow: 479 rrow: 479)
leaf: 0x1016412 16868370 (12: nrow: 479 rrow: 479)
leaf: 0x1016413 16868371 (13: nrow: 478 rrow: 478)
leaf: 0x1016414 16868372 (14: nrow: 479 rrow: 479)
leaf: 0x1016415 16868373 (15: nrow: 479 rrow: 479)
leaf: 0x1016416 16868374 (16: nrow: 479 rrow: 479)
leaf: 0x1016417 16868375 (17: nrow: 479 rrow: 479)
leaf: 0x1016418 16868376 (18: nrow: 478 rrow: 478)
leaf: 0x1016419 16868377 (19: nrow: 475 rrow: 475)
leaf: 0x101641a 16868378 (20: nrow: 449 rrow: 449)
leaf: 0x101641b 16868379 (21: nrow: 449 rrow: 449)
leaf: 0x101641c 16868380 (22: nrow: 449 rrow: 449)
leaf: 0x101641d 16868381 (23: nrow: 449 rrow: 449)
leaf: 0x101641e 16868382 (24: nrow: 449 rrow: 449)
leaf: 0x101641f 16868383 (25: nrow: 449 rrow: 449)
leaf: 0x1016421 16868385 (26: nrow: 449 rrow: 449)
leaf: 0x1016422 16868386 (27: nrow: 449 rrow: 449)
leaf: 0x1016423 16868387 (28: nrow: 449 rrow: 449)
leaf: 0x1016424 16868388 (29: nrow: 449 rrow: 449)
leaf: 0x1016425 16868389 (30: nrow: 449 rrow: 449)
leaf: 0x1016426 16868390 (31: nrow: 449 rrow: 449)
leaf: 0x1016427 16868391 (32: nrow: 449 rrow: 449)
leaf: 0x1016428 16868392 (33: nrow: 449 rrow: 449)
leaf: 0x1016429 16868393 (34: nrow: 449 rrow: 449)
leaf: 0x101642a 16868394 (35: nrow: 449 rrow: 449)

每一行的第一列表示节点类型:branch表示分支节点(包括根节点),而leaf则表示叶子节点;
第二列表示十六进制表示的节点的地址;DBA
第三列表示十进制表示的节点的地址 DBA
第四列表示相对于前一个节点的位置,根节点从0开始计算,其他分支节点和叶子节点从-1开始计算
第五列的nrow表示当前节点中所含有的索引条目的数量。比如我们可以看到根节点中含有的nrow为9,表示根节点中含有9个索引条目,分别指向9个分支节点;
根节点及分支节点第六列中的level表示分支节点的层级,对于叶子节点来说level都是0;
叶子节点第六列中的rrow表示有效的索引条目(因为索引条目如果被删除,不会立即被清除出索引块中。
所以nrow减rrow的数量就表示已经被删除的索引条目数量)的数量,比如对于第一个leaf来说,其rrow为359,也就是说该叶子节点中存放了359个可用索引条目,分别指向表warecountd的359条记录。

9.

SQL> select dbms_utility.data_block_address_file(16868355) "file",dbms_utility.data_block_address_block(16868355) "block" from dual;

file block
---------- ----------
4 91139
注:data_block_address_file:This function gets the file number part of a data block address

使用查询视图进行验证:

SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments where segment_name=‘IDX_IT‘;

HEADER_FILE HEADER_BLOCK
----------- ------------
4 91138

注:这个段头文件,所以需要+1,如此就是index的根节点

10.dump出file 4 block 91139

SQL> alter system dump datafile 4 block 91139;

System altered.

vi /app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_5816.trc

Branch block dump
=================
header address 47125592066636=0x2adc482cca4c
kdxcolev 1 --其中的kdxcolev表示索引层级号,这里由于我们转储的是根节点,所以其层级号为1
KDXCOLEV Flags = - - -
kdxcolok 0 --kdxcolok表示该索引上是否正在发生修改块结构的事务
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y --kdxcoopc表示内部操作代码
kdxconco 2 --kdxconco表示索引条目中列的数量(列 rowid,索引值)
kdxcosdc 0 --kdxcosdc表示索引结构发生变化的数量,当你修改表里的某个索引键值时,该值增加;
kdxconro 221 --kdxconro表示当前索引节点中索引条目的数量,但是注意,不包括kdxbrlmc指针
kdxcofbo 470=0x1d6 --kdxcofbo表示当前索引节点中可用空间的起始点相对当前块的位移量
kdxcofeo 5868=0x16ec --kdxcofeo表示当前索引节点中可用空间的最尾端的相对当前块的位移量
kdxcoavs 5398 --kdxcoavs表示当前索引块中的可用空间总量,等于 kdxcofeo-kdxcofbo得到的。
kdxbrlmc 16868356=0x1016404 --kdxbrlmc表示分支节点的地址,该分支节点存放了索引键值小于row#0(在转储文档后半部分显示)所含有的最小值的所有节点信息
kdxbrsno 0 --kdxbrsno表示最后一个被修改的索引条目号,这里看到是0,表示该索引是新建的索引;
kdxbrbksz 8056 --kdxbrbksz表示可用数据块的空间大小
kdxbr2urrc 0
row#0[8047] dba: 16868357=0x1016405
col 0; len 3; (3): c2 05 57 --col 0表示该分支节点所链接的最小键值
col 1; TERM --如果根节点下没有其他的分支节点,则col 1为TERM
row#1[8038] dba: 16868358=0x1016406
col 0; len 3; (3): c2 0a 42
col 1; TERM
row#2[8029] dba: 16868359=0x1016407
col 0; len 3; (3): c2 0f 2d
col 1; TERM
row#3[8020] dba: 16868360=0x1016408
col 0; len 3; (3): c2 14 18
col 1; TERM
row#4[8011] dba: 16868361=0x1016409
col 0; len 3; (3): c2 19 03
col 1; TERM

在获得最终物理块的过程中,我们不能同时读取多个块,因为我们在没有获得当前块的时候是不知道接下来应该访问哪个块的。因此,在索引上访问数据块时,会对应到db file sequential read等待事件,其根源在于我们是按照顺序从一个索引块跳到另一个索引块,从而找到最终的索引块的

那么对于全表扫描来说,则不存在访问下一个块之前需要先访问上一个块的情况。全表扫描时,oracle知道要访问所有的数据块,因此唯一的问题就是尽可能高效的访问这些数据块。因此,这时oracle可以采用同步的方式,分几批,同时获取多个数据块。这几批的数据块在物理上可能是分散在表里的,因此其对应到db file scattered read等待事件

2.B树索引的对于插入(INSERT)的管理
对于第一种情况来说,比较简单。当在一个充满了数据的表上创建索引(create index命令)时,oracle会先扫描表里的数据并对其进行排序,然后生成叶子节点。生成所有的叶子节点以后,根据叶子节点的数量生成若干层级的分支节点,最后生成根节点。这个过程是很清晰的

3个字节行头+1个字节列长+150个字节列本身+1个字节列长+6个字节ROWID

当第一个叶子节点充满以后,进行分裂时,先获得两个可用的索引块作为新的叶子节点,然后将当前该叶子节点里所有的索引条目拷贝到这两个新获得的叶子节点,
最后将原来的叶子节点改变为根节点.

analyze index idx_it validate structure;
不过要注意一点,就是该命令有一个坏处,就是在运行过程中,会锁定整个表,从而阻塞其他session对表进行插入、更新和删除等操作。
这是因为该命令的主要目的并不是用来填充index_stats视图的,其主要作用在于校验索引中的每个有效的索引条目都对应到表里的一行,
同时表里的每一行数据在索引中都存在一个对应的索引条目。为了完成该目的,所以在运行过程中要锁定整个表,
同时对于很大的表来说,运行该命令需要耗费非常多的时间

索引删除:总结

1) 当删除表里的一条记录时,其对应于索引里的索引条目并不会被物理的删除,只是做了一个删除标记。
2) 当一个新的索引条目进入一个索引叶子节点的时候,oracle会检查该叶子节点里是否存在被标记为删除的索引条目,如果存在,则会将所有具有删除标记的索引条目从该叶子节点里物理的删除。
3) 当一个新的索引条目进入索引时,oracle会将当前所有被清空的叶子节点(该叶子节点中所有的索引条目都被设置为删除标记)收回,从而再次成为可用索引块。

对于如何判断索引是否出现碎片,方法非常简单:直接运行ANALYZE INDEX … VALIDATE STRUCTURE
命令,然后检查index_stats视图的pct_used字段,如果该字段过低(低于50%),则说明存在碎片

索引的更新
索引的更新即 删除+插入的组合。

本文参考:http://blog.csdn.net/csd_xuming/article/details/7542584
学习到很多,谢谢!

时间: 2024-10-26 18:11:17

B tree索引学习总结的相关文章

Tree的学习

demo代码如下.欢迎指正与讨论. #include <iostream> #include <queue> #include <stack> using namespace std; template <typename T>  struct BinaryNode{ T elem; BinaryNode *left; BinaryNode * right; BinaryNode(T d, BinaryNode *l=NULL, BinaryNode *r=

索引学习 查找 数据结构 梳理

索引是啥? 索引是数据结构,在数据结构有一章叫查找,在国外的一本书上名字就找索引. 准确的说就是: 加快查找的数据结构. 查找的那一章: 1.有序数组的二分查找 2.二叉查找 ,在此处,为了效率防止退化,引入了平衡的调整. 3.在上述的平衡的定义,为左右高度至多差1,要求太严,调整频露高,于是红黑树应运而生,它对平衡的定义要求最长的比最短的最多2倍,降低平衡要求的目的是提高性能. 红黑树的5条性质如下: 1.节点为黑或红. 2.根和叶子为黑. 3.不能出现红红. 4,每个节点到叶子黑色高度相同.

B+tree索引

B+Tree索引 如上图,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1.P2.P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块.真实的数据存在于叶子节点即3.5.9.10.13.15.28.29.36.60.75.79.90.99, 非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17.35并不真实存在于数据表中. B+索引在InnoDB和MyI

复合B*tree索引branch block内是否包含非先导列键值?

好久不碰数据库底层细节的东西,前几天,一个小家伙跑来找我,非要说复合b*tree index branch block中只包含先导列键值信息,并不包含非先导列键值信息,而且还dump了branch block,用以证明他的说法,从常理和SQL的语句执行信息就可以知道,他的说法是有问题的,但如何证明这一点呢?为了证明这点,也麻烦一次,玩玩多年不碰的dump.下面是他证明自己观点的两个dump结果(一个为单键索引,另一个是复合索引): 下面是本人的测试过程和结果: create table t1(c

MongoDB数据模型和索引学习总结

MongoDB数据模型和索引学习总结 1. MongoDB数据模型: MongoDB数据存储结构: MongoDB针对文档(大文件採用GridFS协议)採用BSON(binary json,採用二进制编码)数据格式来存储和交换数据.Bson吸收了JSON schema-less的特点,存储结构松散,不须要像RDB(关系数据)那样事先定义数据存储的元数据结构.另外添加了多种数据类型的支持和优化,使读写更加高效. (1) BSON 支持的数据类型: Double.String.Object.Arra

【连载】关系型数据库是如何工作的?(5) - B+Tree索引

虽然上一章节介绍的二叉搜索树在查询指定值时表现很好,但是当查询两个值之间的多个节点时,就会遇到很大的问题.因为需要遍历整个树的节点,并检查每个节点是否在指定的区间内.而且遍历整颗树是随机磁盘IO(译者注:随机IO会导致频繁的磁头换道,所以相比顺序IO来说非常耗时),所以我们需要找到一种更有效做范围查询的方法.为了解决这个难题,现代数据库修正了之前介绍的二叉搜索树,我们称修正后的数据结构为B+Tree: 只有叶子节点(树最底层的节点,图中橘黄色的节点)存储信息,即:行在表中精确的位置,也就是row

MySQL/MariaDB的 B+ TREE索引

在我们CentOS 7+版本之后的自带镜像中的MariaDB使用的默认引擎是InnoDB引擎: InnoDB引擎自带的特点: 1.InnoDB存储引擎将数据存储于"表空间"中: 2.支持事务 3.精细锁粒度支持:表级锁.页级锁.行级锁.间隙锁: 4.支持聚集索引,主键索引以及辅助索引,自适应的Hash索引: 简要介绍一下事务: 所谓事务:就是一组原子性的SQL查询或者是一个或多个SQL语句组成的独立的操作单元: 一个最简单易懂的事务例子: A 借 B 100块钱,A 得到100,则相应

Mysql B-Tree和B+Tree索引

Mysql B-Tree和B+树索引 Mysql加快数据查找使用B-Tree数据结构存储索引数据,InnoDB存储引擎实际使用B+Tree.下面首先介绍下B-Tree和B+Tree的区别: 一.B树和B+树索引(手绘图简要说明) 1.B-Tree索引: 2.B+Tree索引: 3.B-Tree 和B+Tree索引查找原理: 非叶子节点存储索引关键字,叶子节点指针指向的是被索引的数据.节点槽中存放了指向子节点的指针(可以理解为两个关键字之间),存储引擎根据这些指针向下层查找.通过比较节点页的值和要

数据库索引学习

一.索引介绍 数据库索引调优是一项技术活,不能仅仅靠理论,因为实际情况千变万化,而且各种数据库本身存在很复杂的机制,如查询优化策略和各种引擎的实现等.但同时这些理论是索引调优的基础,只有在明白理论的基础上,才能对调优策略进行合理推断并了解其背后的机制,然后结合实践中不断的实验和摸索. 索引其实就是在数据库存储数据之外,还维护着另外的满足某种查询算法的数据结构,这些数据结构再以某种方式指向真实的存储数据,然后在现有的数据结构上实现快速查询.(找了张很不错的二叉树的图来理解索引,现在大多的索引都是B