连接表是否应该创建为索引组织表(Clustered Indexes)?

时间:2012-01-01 21:59:09

标签: sql-server oracle indexing clustered-index

一般来说......应该将表(即关联表)创建为索引组织表(Oracle),聚簇索引(SQL Server)....或普通旧堆表(在2列上具有单独的索引)

我看待的方式,优点是:

速度提升。 你正在避免堆表查找。

空间改善。 你完全取消了堆表,所以你可能节省了大约30%的空间。

缺点:

索引跳过扫描(仅适用于Oracle)..将比全表扫描更快,但比索引扫描慢。因此,对复合键的第二列的搜索将稍微慢一点(Oracle),慢得多(MSSQL)。

完整索引扫描将比全表扫描慢 - 所以如果大多数时候基于成本的优化器正在进行哈希联接(不利用索引)......你可能会觉得性能更差。 (假设RDBMS不首先过滤表)。

这让我怀疑,如果您主要要做Hash Joins,那么Join Tables是否真的需要任何类型的索引。

3 个答案:

答案 0 :(得分:3)

我只是列出并讨论一些可能的解决方案,希望能帮助您做出决定。 “联合表”包含两列或三列。左表的外键(例如a)和右表的外键(例如b)。可选列是“联合表”的行标识,例如id

解决方案1:列a,b。没有聚集索引(堆),(a,b)(b,a) 上的索引 两列都存储在三个位置。它支持ab上的搜索,而b的搜索不需要书签查找,因为a部分是(b,a)索引。体面的选择,但三重存储似乎是一种浪费。堆没有用,但必须在insertupdate查询期间进行维护。

解决方案2:列a, b(a,b)上的聚簇索引,(b,a)上的索引
所有数据都存储两次。无需书签查找即可在ab上投放。这将是最佳实践方法。它以交换磁盘存储速度。

解决方案3:列a, b(a,b)上的聚集索引
所有数据仅存储一次。它可以在a上进行搜索,但不能在b上进行搜索。从右表到左表需要进行表扫描。这会换取磁盘空间的速度。 (您的问题提到散列连接。散列连接始终执行完整扫描。)

解决方案4:列id, a, b。聚集索引(id)(a)上的索引和(b)
ab的搜索都需要书签查找。 ab都存储在磁盘上两次,一次存储在自己的索引中,一次存储在聚簇密钥中。这是我能想到的最糟糕的解决方案。

此列表并非详尽无遗。解决方案2将是一个很好的默认选择。我会继续这样做,除非另一个解决方案在测试中证明自己要好得多。

答案 1 :(得分:3)

我个人的经验法则是创建两个表关联实体作为索引组织表,主键约束是我期望更常用的访问“方向”。然后,我通常会添加一个唯一索引来覆盖键的反向顺序,因此在所有情况下,优化器都应该能够使用唯一扫描或范围扫描访问。

三表(或更多)关联实体通常需要更多分析。

此外,优化器将使用具有散列连接操作的索引;通常是快速全扫描,但仍然是索引。

答案 2 :(得分:0)

我不熟悉Oracle术语,但对于SQL Server,问题的措辞令人困惑。澄清:

  • 聚集索引确定表的物理顺序
  • 非聚集索引基本上是主表的副本,按指定的键排序
  • 您可以在非聚集索引中分配(“包含”)其他列,这可以允许查询优化器使用这些列来满足查询,而不是执行书签查找。
  • 堆是没有任何索引的表。对堆的所有查询都需要扫描。
  • 完整的非聚簇索引扫描比全表扫描更快,只要索引比表更窄并且您不需要书签查找。

因此,考虑到这一点,用于连接的密钥通常应该具有与之关联的聚簇索引或非聚簇索引,以避免表扫描。您可以根据需要在非聚簇索引中包含其他列 - 并且优先使用聚簇索引来覆盖连续范围的键值,并且每行可以访问许多列。