【问题标题】:Should Join Tables typically be created as Index Organized Tables (Clustered Indexes)?连接表通常应该创建为索引组织表(聚集索引)吗?
【发布时间】:2012-01-31 12:32:46
【问题描述】:

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

我看的方式,优点是:

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

空间改善。 您完全消除了堆表,因此您可能节省了大约 30% 的空间。

缺点:

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

全索引扫描会比全表扫描慢 - 因此,如果基于成本的优化器大部分时间都在执行哈希连接(不利用索引)......您可能会遇到更差的性能。 (假设 RDBMS 不首先过滤表)。

如果您主要进行哈希连接,这让我怀疑连接表是否真的需要任何类型的索引。

【问题讨论】:

  • 你应该在两列上有一个复合主键,无论如何都会在它们上创建一个唯一索引。
  • reg "全索引扫描会比全表扫描慢":Oracle 也有 INDEX FAST FULL SCAN,它基本上和全表访问一样快。见use-the-index-luke.com/sql/explain-plan/oracle/…。另请参阅我的评论 reg。下面是哈希连接索引。
  • @MarkusWinand - 好点...感谢伟大的网站(IMO 它是在线索引上最简洁的 dbms 不可知源)。

标签: sql-server oracle indexing clustered-index


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    我只是列出并讨论一些可能的解决方案,希望它们能帮助您做出决定。 “联合表”包含两列或三列。左表的外键,比如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 将是一个不错的默认选择。除非另一种解决方案在测试中证明自己明显更好,否则我会这样做。

    【讨论】:

    • 同意,除了散列连接的东西。哈希连接可以将索引用于独立的 where 谓词。这种连接中可能没有独立的 where 谓词,因此该语句对于这种情况可能是正确的。但这取决于实际查询。见use-the-index-luke.com/sql/join/hash-join-partial-objects
    • @Andomar:我喜欢这种分析。三表关联怎么样? (a,b,c) - clustered(b,c,a)(c,a,b) 上的索引可以吗?
    【解决方案3】:

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

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

    因此,考虑到这一点,用于连接的键通常应该具有与之关联的聚集索引或非聚集索引,以避免表扫描。您可以根据需要在非聚集索引中包含额外的列,并且更喜欢聚集索引用于涵盖连续键值范围且每行可访问许多列的查询。

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      • 1970-01-01
      • 2012-12-30
      • 2016-03-29
      • 2015-08-11
      相关资源
      最近更新 更多