`

复合索引branch block上存储几个列的信息

阅读更多

[分享] 复合索引branch block上存储几个列的信息

这是很早之前研究的问题,已经忘记了是什么案例导致去研究这个问题。

 

不过这个问题本省就很有意思,当在两个或者多个列上创建索引时,究竟branch block中会纪录几个列的信息?

 

首先我们知道branch block中存储结构大致是这样的 pointer - value - pointer - value - pointer.其中pointer指向leaf block或者下一层branch block.

 

那么这个value的值就是为了区分左右指针所指向的两个leaf block(或者下一层branch block中)的值,这样从root -> branch -> leaf的时候才能准确定位到leaf block.

在提供答案前,首先给出几种不同的论点

 

1.不管建立在多少列上,branch block中只存储leading column信息

 

2. 如果建立在n个列上,branch block中存储n-1列的信息

 

3. branch block上存储所有列的信息.

 

这三种观点都有问题,首先观点一

 

如果这个索引的leading column的可选择性很差,例如status或者flag这样的列,distinct value很少

 

这时候如果索引建立在 status, id)上,对于

 

select * from table where status=0 and id=12345这样的查询,range scan并不能准确定位到 leaf block

 

对于观点二,在n=2的时候显然也可以用上面的例子来推翻

 

对于观点三,是可以正确定位到leaf block,但是如果对于像

 

index(id,name) 其中name 假定name字段类型为varchar(1000),这样的索引效率也不好

 

事实上因为id列可选择性很好,一般不需要再存储name值到branch block中就可以区分左右的block

 

branch block中存储的name列的值浪费了branch block的空间,

 

而我们知道单个branch block中能够存储值的多少直接影响了树的高度,而树的高度显然直接影响了index的效率

 

通过上面的分析,以上的三种观点都是错误的,那么oracle究竟如何来存储列信息才能既做到准确定位leaf block又不存储多余的值呢?

 

这里首先给出试验的结果,我没有找到官方文档或者其他的文章来解释这个结论,不过通过试验来看结论是很清楚的,而且也符合上面提到的两种考虑因素。

 

其实刚刚我们被限制住的原因是一直认为branch block中存储的列的个数是个常数,但事实上存储几个列是变化的。

 

这个值只需要区分其左右指针所指向的两个block的值就可以了,

 

更简单的说,当oracle从上到下走到这个branch block的时候,

 

通过这个值可以准确的知道向左走还是向右走,

 

举个例子,我们上面一开始提到的索引例子,

 

第一个是 indexstatus, id) , 如果左边block的最大值为(0,33),右边block的最小值为(0,35)

 

因为此时单纯从第一列不能区分两个block,这时就需要存储两列的信息

 

如果左边block最大值为(0,100),右边block最小值为(1,1)

 

因为此时从第一列就可以区分出两个block,所以只需要存储第一列的信息

 

这样对于

 

select * from table where status=0 and id=12345

 

查询,通过branch block中的值既可以知道“向左走,向右走”,准确定位leaf block

 

又可以避免不必要的浪费branch block空间,避免树高度不必要的增高

 

下面是试验的过程,直接copy以前自己发的邮件,懒得翻译了

 

We discussed the internal storage rule for composite index last time, but we didn’t get conclusion yet.

 

So I did a test for this.

 

SQL> create table test(n1 int,n2 int ,n3 int,v1 varchar2(2000),v2 varchar2(2000),v3 varchar2(2000));

 

Table created.

 

SQL> begin

2 for i in 1..1000 loop

3 insert into test values(0,i,i,rpad(’a',2000),rpad(’a',2000),rpad(’a',2000));

4 end loop;

5 end;

6 /

 

PL/SQL procedure successfully completed.

 

insert 1000 rows, the format is like this

0,1,1,xxxxxx,xxxxxxxxxx

0,2,2,xxxxxx,xxxxxxxxxx

0,3,3, xxxxxx,xxxxxxxxxx

……..

0,1000,1000, xxxxxx,xxxxxxxxxx

 

SQL> commit;

 

Commit complete.

 

create 7 indexes on this table, the naming rule is index_

 

_N (number) V (varchar)

 

SQL> create index index_2_nv on test(n1,v1);

 

Index created.

 

SQL> create index index_2_vn on test(v1,n1);

 

Index created.

 

SQL> create index index_3_nnv on test(n1,n2,v1);

 

Index created.

 

SQL> create index index_3_nvn on test(n1,v1,n2);

 

Index created.

 

SQL> create index index_4_nnnv on test(n1,n2,n3,v1);

 

Index created.

 

SQL> create index index_4_nnvn on test(n1,n2,v1,n3);

 

Index created.

 

SQL> create index index_5_nnnvv on test (n1,n2,n3,v1,v2);

 

Index created.

 

SQL> analyze table test compute statistics;

 

Table analyzed.

 

SQL> select index_name,PREFIX_LENGTH,BLEVEL,LEAF_BLOCKS from user_indexes

2 where lower(index_name) in (’index_2_nv’,'index_2_vn’,'index_3_nnv’,'index_3_nvn’,

3 ‘index_4_nnnv’,'index_4_nnvn’,'index_5_nnnvv’);

 

INDEX_NAME PREFIX_LENGTH BLEVEL LEAF_BLOCKS

—————————— ————- ———- ———–

INDEX_2_NV 5 334

INDEX_2_VN 5 334

INDEX_3_NNV 1 334

INDEX_3_NVN 5 334

INDEX_4_NNNV 1 334

INDEX_4_NNVN 1 334

INDEX_5_NNNVV 2 1000

 

7 rows selected.

 

You see, three indexes (INDEX_2_NV, INDEX_2_VN, INDEX_3_NVN) have level5. This means these indexes’ branch block contains varchar2000.

 

Then I dump these indexes’ root block to confirm this.

 

SQL> select segment_name,file_id,block_id from dba_extents where

2 lower(segment_name) in (’index_2_nv’,'index_2_vn’,'index_3_nnv’,'index_3_nvn’,

index_4_nnnv’,'index_4_nnvn’,'index_5_nnnvv’) and extent_id=0 order by segment_name 3 ;

 

SEGMENT_NAME FILE_ID BLOCK_ID

—————————— ———- ———-

INDEX_2_NV 9 16082

INDEX_2_VN 9 16097

INDEX_3_NNV 9 13587

INDEX_3_NVN 1 22053

INDEX_4_NNNV 1 32702

INDEX_4_NNVN 1 62230

INDEX_5_NNNVV 1 61697

 

7 rows selected.

SQL> @temp.sql

SQL> alter system dump datafile 9 block 16083;

System altered.

 

SQL> alter system dump datafile 9 block 16098;

System altered.

 

SQL> alter system dump datafile 9 block 13588;

System altered.

 

SQL> alter system dump datafile 1 block 22054;

System altered.

 

SQL> alter system dump datafile 1 block 32703;

System altered.

 

SQL> alter system dump datafile 1 block 62231;

System altered.

 

SQL> alter system dump datafile 1 block 61698;

System altered.

 

.

 

It’s weird. The index INDEX_2_NV and INDEX_2_VN only have 2 columns.But in the root block dump file, we can find col0,col1 and col2(maybesomething related to rowid, I guess).

 

I am not sure about what the third col is, but it’s clear that the number of columns in branch block is related about the data.

 

0,1,1,xxxxxx,xxxxxxxxxx

0,2,2,xxxxxx,xxxxxxxxxx

0,3,3, xxxxxx,xxxxxxxxxx

……..

0,1000,1000, xxxxxx,xxxxxxxxxx

 

The index INDEX_2_NV, INDEX_2_VN can’t distinguish the leaf blocksusing the prefix two columns, so it added the third column (unknown,maybe something related to rowid, I guess).

 

The indexes INDEX_3_NNV, INDEX_4_NNNV, INDEX_4_NNVN and INDEX_5_NNNVVcan distinguish the leaf blocks using the prefix two columns, so thebranch blocks only contain 2 columns.

 

The index INDEX_3_NVN can should use three columns to distinguish theleft/right leaf blocks, so it contains 3 columns (because the prefixtwo columns’ values are the same).

 

You can check the dump file xfan_ora_25936.trc for details.

 

So I guess that the number of columns stored in branch block is related to linked leaf blocks’ data.

The columns which stored in branch blocks need to distinguish the left/right linked leaf blocks.

If the rule for composite index is like I guessed, then the columnsstored in branch blocks maybe different in one index branch block!!

 

So I did another test to prove this:

 

SQL> create table test2(n1 int,n2 int,n3 int,v1 varchar2(2000),v2 varchar2(2000));

 

Table created.

 

SQL> create index test_idx on test2(n1,n2,n3,v1,v2);

 

Index created.

 

SQL> begin

2 for i in 1..1000 loop

insert into test2 values(0,0,i,rpad(’a',2000),rpad(’a',2000));

end loop;

end;

/ 3 4 5 6

 

PL/SQL procedure successfully completed.

 

Insert first 1000 rows like this:

 

0, 0, 1, xxxxx,xxxxxx

0, 0, 2, xxxxx,xxxxxx

0, 0, 3, xxxxx,xxxxxx

……

0, 0, 1000, xxxxx,xxxxxx

 

SQL> SQL>

SQL> begin

2 for i in 1001..2000 loop

insert into test2 values(0,i,i,rpad(’a',2000),rpad(’a',2000));

end loop;

end;

/ 3 4 5 6

 

Then insert other 1000 rows like this:

0,1,1,xxxx,xxxx

0,2,2,xxxx,xxxx

0,3,3,xxxx,xxxx

…….

0,1000,1000,xxxx,xxxx

 

Then I did treedump and branch block dump.

 

Here is a snippet of the branch block dump:

 

row#454[2145] dba: 4218395=0×405e1b

col 0; len 1; (1): 80

col 1; len 1; (1): 80

col 2; len 3; (3): c2 0a 64

col 3; TERM

row#455[2133] dba: 4218396=0×405e1c

col 0; len 1; (1): 80

col 1; len 1; (1): 80

col 2; len 2; (2): c2 0b

col 3; TERM

row#456[2124] dba: 4218397=0×405e1d

col 0; len 1; (1): 80

col 1; len 1; (1): c2

col 2; TERM

row#457[2113] dba: 4218398=0×405e1e

col 0; len 1; (1): 80

col 1; len 3; (3): c2 0b 03

col 2; TERM

row#458[2102] dba: 4218399=0×405e1f

col 0; len 1; (1): 80

col 1; len 3; (3): c2 0b 04

col 2; TERM

 

You see, the numbers of columns changed in one branch block!!

 

The attachment index.trc is the dump file

 

So the conclusion is that the number of columns stored in branch block is related to linked leaf blocks’ data.

 

The branch block will store as less columns as possible to distinguish the left/right leaf blocks it linked

 

分享到:
评论

相关推荐

    oracle 索引创建.ppt

    - **复合索引**:对于多列查询,可以创建复合索引,将多个列组合在一起,提高查询效率。索引顺序应根据查询条件的频率和选择性进行优化。 - **覆盖索引(Covering Index)**:如果索引包含了查询所需的所有列,那么...

    branch prediction using Two Levels of Branch History

    这种模型通常包括一个较小的分支目标缓冲器(Branch Target Buffer, BTB)以及一个较大的模式历史表(Pattern History Table, PHT),用于存储分支执行历史和模式历史。 2. **九种变体**:通过对基础模型进行不同...

    non-unique index branch and leaf block structure

    标题“非唯一索引分支和叶块结构”指的是数据库管理系统中的数据存储结构,特别是与B树(B-tree)或B+树(B+tree)相关的概念。这些数据结构在数据库索引中扮演着核心角色,特别是在关系型数据库系统中,如MySQL、...

    select-branch用于快速检出本地git分支的CLI工具

    这将在当前分支的基础上创建一个名为`feature/new-feature`的新分支,并立即检出它。 4. **搜索分支** 如果你的分支很多,可以使用`-s`或`--search`选项进行模糊搜索,输入部分分支名来筛选: ```bash select...

    s1 第三章Branch类

    Branch类通常有一个创建分支的方法,例如`createNewBranch(String branchName)`,这个方法会根据给定的名字创建一个新的分支。 2. **切换分支**:在开发过程中,开发者可能需要在不同分支间切换。`switchToBranch...

    intel branch trace store

    在Intel处理器架构中,"Intel Branch Trace Store"(BTS)是一种硬件辅助的性能监控功能,它用于记录程序执行过程中的分支历史信息。这个技术主要目的是为了帮助软件开发者和性能分析人员理解程序的控制流,优化代码...

    简易 MIPS 结构 Branch部分

    1. **MIPS 分支指令**:MIPS提供了几种不同的分支指令,如`beq`(Branch if Equal)、`bne`(Branch if Not Equal)、`blez`(Branch if Less Than or Equal to Zero)、`bgez`(Branch if Greater Than or Equal to...

    NetScaler家族的新成员——Branch Repeater》.

    5. **SDX整合**:与NetScaler SDX(Software Defined Exchange)的整合,使得Branch Repeater能够在一个物理平台上虚拟化运行,提高了资源利用率和管理效率。 6. **经济实惠**:Branch Repeater VPX Express版本...

    Branch Prediction For Free

    相比之下,《Branch Prediction For Free》这篇文章介绍了一种基于程序本身的静态分支预测方法(program-based branch prediction),这种方法无需额外的运行时信息即可实现有效的分支预测。 #### 二、文章摘要解读...

    oracle索引类型及扫描方式大整理new

    它基于二叉树原理,由分支块(branch block)和叶块(leaf block)构成,能够高效地处理高基数数据列的检索。所谓高基数,指的是该列拥有大量不同的值。B\*Tree索引特别适用于当所需检索的行数占总行数比例较低的情况,...

    Oracle_Index 索引2

    B*Tree索引是最常用的索引类型之一,其结构基于二叉树,由分支块(branch block)和叶块(leaf block)构成。分支块用于存储指向其他分支块或叶块的指针,以及用于导航的键值;叶块则直接存储索引键值及其对应的行标识符...

    oracle 索引创建

    4. **使用复合索引**:当查询条件涉及多个列时,可以考虑创建复合索引以提高查询效率。 #### 六、案例分析 从提供的部分数据内容来看,“Rootblock”、“Branch blocks”、“Leaf blocks”分别对应于B树索引的根...

    spark-branch-2.3.zip

    在Spark 2.3中,主要包含以下几个关键组件: 1. Spark Core:这是Spark的基础模块,负责任务调度、内存管理、故障恢复、与存储系统交互等功能。Spark Core提供了一种通用的计算模型,使得其他模块如Spark SQL、...

    西安电子科技大学MySQL数据库上机2答案

    在这个任务中,学生需要完成以下几个关键知识点: 1. **视图的创建**: 视图是数据库中的虚拟表,它根据用户定义的SQL查询结果动态生成。在本例中,创建了一个名为`branch_detail`的视图,用来显示每个支行的存款...

    CDDFuse: Correlation-Driven Dual-Branch 论文

    CDDFuse(Correlation-Driven Dual-Branch Feature Decomposition)是一种用于多模态图像融合的深度学习方法,主要针对如何有效建模跨模态特征并分解出特定模态和共享模态特征的挑战。论文的目的是在融合图像中保留...

    binary matrix with maximum branch number

    关于标题“binary matrix with maximum branch number”和描述“Construction method for binary matrix with maximum branch number”的知识点,主要涉及到二进制矩阵及其分支数概念以及构造具有最大分支数的二进制...

    SVN trunk, branch, tag merge 等的应用

    每当项目达到一个稳定版本,如1.0、2.0等,开发者会在trunk或branch上创建一个tag,以记录这个版本的所有代码。tag不应该被修改,它是项目历史的一个固定点,可以随时回溯查阅。 4. **Merge**:Merge是将代码从一个...

    社交讨论平台Branch如何重构信息分享规则.docx

    社交讨论平台Branch致力于重构信息分享规则,通过其独特的方式促进高质量的对话和深度交流。该平台自2021年3月上线以来,已经逐步发展并开放给所有用户。Branch的核心理念是创造一个像围坐在同一张桌子旁进行深入...

    oracle的索引初步学习.doc

    在这个列上创建了一个B树索引。 - **数据块大小**:默认情况下,Oracle的数据块大小为8KB。 - **PCTFREE**:默认值为10%,这意味着每个数据块中只有90%的空间可以用于存储数据。实际上,这个值会进一步减少至大约87...

    在SVN中使用分支/Branch进行版本控制

    ### 在SVN中使用分支/Branch进行版本控制 #### 1. 名词缩略语释义 在探讨如何在Subversion (SVN) 中利用分支进行版本控制之前,我们首先需要理解一些基本术语。 - **PCM** (Project Configuration Manager): 项目...

Global site tag (gtag.js) - Google Analytics