一般来说......应该将表(即关联表)创建为索引组织表(Oracle),聚簇索引(SQL Server)....或普通旧堆表(在2列上具有单独的索引)
我看待的方式,优点是:
速度提升。 你正在避免堆表查找。
空间改善。 你完全取消了堆表,所以你可能节省了大约30%的空间。
缺点:
索引跳过扫描(仅适用于Oracle)..将比全表扫描更快,但比索引扫描慢。因此,对复合键的第二列的搜索将稍微慢一点(Oracle),慢得多(MSSQL)。
完整索引扫描将比全表扫描慢 - 所以如果大多数时候基于成本的优化器正在进行哈希联接(不利用索引)......你可能会觉得性能更差。 (假设RDBMS不首先过滤表)。
这让我怀疑,如果您主要要做Hash Joins,那么Join Tables是否真的需要任何类型的索引。
答案 0 :(得分:3)
我只是列出并讨论一些可能的解决方案,希望能帮助您做出决定。 “联合表”包含两列或三列。左表的外键(例如a
)和右表的外键(例如b
)。可选列是“联合表”的行标识,例如id
。
解决方案1:列a,b
。没有聚集索引(堆),(a,b)
和(b,a)
上的索引
两列都存储在三个位置。它支持a
和b
上的搜索,而b
的搜索不需要书签查找,因为a
部分是(b,a)
索引。体面的选择,但三重存储似乎是一种浪费。堆没有用,但必须在insert
和update
查询期间进行维护。
解决方案2:列a, b
。 (a,b)
上的聚簇索引,(b,a)
上的索引
所有数据都存储两次。无需书签查找即可在a
和b
上投放。这将是最佳实践方法。它以交换磁盘存储速度。
解决方案3:列a, b
。 (a,b)
上的聚集索引
所有数据仅存储一次。它可以在a
上进行搜索,但不能在b
上进行搜索。从右表到左表需要进行表扫描。这会换取磁盘空间的速度。 (您的问题提到散列连接。散列连接始终执行完整扫描。)
解决方案4:列id, a, b
。聚集索引(id)
,(a)
上的索引和(b)
a
或b
的搜索都需要书签查找。 a
和b
都存储在磁盘上两次,一次存储在自己的索引中,一次存储在聚簇密钥中。这是我能想到的最糟糕的解决方案。
此列表并非详尽无遗。解决方案2将是一个很好的默认选择。我会继续这样做,除非另一个解决方案在测试中证明自己要好得多。
答案 1 :(得分:3)
我个人的经验法则是创建两个表关联实体作为索引组织表,主键约束是我期望更常用的访问“方向”。然后,我通常会添加一个唯一索引来覆盖键的反向顺序,因此在所有情况下,优化器都应该能够使用唯一扫描或范围扫描访问。
三表(或更多)关联实体通常需要更多分析。
此外,优化器将使用具有散列连接操作的索引;通常是快速全扫描,但仍然是索引。
答案 2 :(得分:0)
我不熟悉Oracle术语,但对于SQL Server,问题的措辞令人困惑。澄清:
因此,考虑到这一点,用于连接的密钥通常应该具有与之关联的聚簇索引或非聚簇索引,以避免表扫描。您可以根据需要在非聚簇索引中包含其他列 - 并且优先使用聚簇索引来覆盖连续范围的键值,并且每行可以访问许多列。