4

我一直在思考两个问题。在互联网上找不到任何关于此的资源。dbms 如何处理它?还是他们?尤其是甲骨文。

在问题之前,这里是一个例子:假设我有一个主表“MASTER”和从表“SLAVE”。主表有一个“ID”列,它是主键,索引是由Oracle创建的。从表有外键“MASTER_ID”,它指的是主表和“SLAVE_NO”。这两个加起来就是从表的主键,又被索引了。

 **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-tree 索引更加平衡吗?(好吧,每个主表可能没有确切数量的从属记录,但仍然似乎比倒序好)

有人知道吗?还是意见?

4

2 回答 2

7

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

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

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

相反,为拆分页面创建一个兄弟,并且新记录(可能加上旧页面中的一些记录)转到新页面。指向新页面的指针被添加到父页面。

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

这些拆分可以传播到根页面,其拆分是唯一增加索引深度的东西(并且一次对所有页面执行此操作)。

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

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

SLAVE将表的主键列反向排序会更明智吗?

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

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

当引擎从master中找到带有索引或其他内容的记录时,这也意味着它已经找到了slave要与该 连接的记录master。反之亦然,定位 aslave也意味着定位它的master

于 2012-06-05T17:18:51.990 回答
4

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

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

您可能不得不担心索引倾斜的唯一情况是您定期从索引左侧删除大部分但不是所有块。例如,如果您决定从索引的左侧删除 90% 的数据,在每个指向数据的叶节点中保留一行,则您的索引可能会变得不平衡,因为某些路径会导致更多的数据比其他路径。Oracle 在索引叶节点完全为空之前不会回收它们,因此您最终可能会使用比实际需要更多的空间来使用索引的左侧。这并不会真正影响系统的性能 - 它更多的是空间利用问题 - 但可以通过在清除数据后合并索引来修复它(或构建清除结构以便您不要'

于 2012-06-05T17:29:04.833 回答