增量列是否使列上的b-tree索引不平衡?

时间:2012-06-05 16:59:13

标签: database performance oracle indexing b-tree

我一直在考虑两个问题。无法在互联网上找到任何关于此的资源。 dbms如何处理它?或者他们呢?尤其是Oracle。

在提出问题之前,这是一个例子:假设我有一个主表“MASTER”和从表“SLAVE”。  主表有一个“ID”列,它是主键,索引由Oracle创建.Slave表具有引用主表和“SLAVE_NO”的外键“MASTER_ID”。这两个一起是slave表的主键,它再次被索引。

 **MASTER**  |  **SLAVE**
     (P) ID <------> (P)(F) MASTER_ID 
                     (P) SLAVE_NO

现在问题;

1-如果MASTER_ID是一个自动增量列,并且没有删除任何记录,这是否会使表的索引失衡? Oracle是否会定期重建索引?据我所知,Oracle仅在构建时平衡索引分支。 Oracle是否会自动重建索引?如果水平上升到某个高水平呢?

2-假设Oracle不会自动重建,除了安排定期重建索引的作业之外,订购SLAVE表的主键列是否更明智?我的意思是代替“MASTER_ID”,“SLAVE_NO”将其命名为“SLAVE_NO”,“MASTER_ID”i,它会帮助奴隶表的b树索引更加平衡吗? (好吧,每个主表可能没有确切数量的从属记录,但仍然看起来好于逆序)

任何人都知道这件事吗?还是意见?

2 个答案:

答案 0 :(得分:7)

  

如果MASTER_ID是一个自动增量列,并且没有删除任何记录,这是否会使表的索引失衡?

Oracle的索引永远不会“不平衡”:索引中的每个叶子与任何其他叶子的深度相同。

没有页面拆分本身会引入一个新级别:叶子页面不会成为新页面的父级,就像在非自平衡树上一样。

相反,会生成拆分页面的兄弟,新记录(可能还有旧页面中的一些记录)会转到新页面。指向新页面的指针将添加到父页面。

如果父页面也是空间不足(无法接受指向新创建的叶页的指针),它也会被拆分,依此类推。

这些拆分可以传播到根页面,根页面的分割是唯一可以增加索引深度的东西(并且可以同时为所有页面执行)。

索引页面另外被组织成双链表,每个列表都在其自己的级别上。如果树不平衡,这将是不可能的。

如果master_id自动递增,则意味着所有拆分都在最后发生(例如称为90/10拆分),这使得最密集的索引成为可能。

  

SLAVE表的主键列反向命令会更明智吗?

不,由于上述原因,它不会。

如果经常加入slavemaster,您可以考虑在CLUSTER索引的两个表中创建master_id。这意味着来自两个表的共享相同master_id的记录将转到相同或附近的数据页面,这使得它们之间的连接速度非常快。

当引擎找到master的记录,带有索引或其他内容时,这也意味着它已经找到了slave中与master加入的记录。反之亦然,找到slave也意味着找到其master

答案 1 :(得分:4)

对于“平衡”的大多数有用定义,MASTER_ID上的b树索引将保持平衡。特别是,根块和任何子块之间的距离将始终相同,并且任何分支中的数据量将至少与任何其他同级分支中的数据量大致相等。

当您将数据插入到序列生成列的索引中时,当任何特定级别的数据量增加时,Oracle将对叶子执行90-10个块分割。例如,如果您有一个可以容纳10行的叶块,当它已满并且您想要添加第11行时,Oracle会创建一个新块,在第一个块中保留前9个条目,在该块中放入2个条目新块,并使用新块的地址更新父块。如果父块需要拆分,因为它为太多子节点保存地址,则会发生类似的过程。这使得指数在其整个生命中相对平衡。 Richard Foote(Oracle索引专家)在When Does an Oracle Index Increase in Height上有一个很好的博客,详细介绍了它的工作原理。

您可能不得不担心索引会出现偏差的唯一情况是您经常删除索引左侧的大部分块而不是所有块。例如,如果您决定从索引的左侧删除90%的数据,而每个叶节点中的一行指向数据,则某些路径会导致数据量大大增加,您的索引会变得不平衡比其他路径。 Oracle不会回收索引叶子节点,直到它们完全为空,因此您可以使用比实际需要更多的空间来结束索引的左侧。这并不会真正影响系统的性能 - 它更多地是一个空间利用问题 - 但是可以通过在清除数据后合并索引来修复(或者构建清除以便你不要留下许多稀疏的块)。