【问题标题】:More tables with the same clustered index, can I omit the PK index on the satellite table?同一个聚集索引的表比较多,可以省略卫星表上的PK索引吗?
【发布时间】:2021-10-28 01:54:11
【问题描述】:

我有多个存储通话数据的表,它们具有相同的聚集索引:start_time (DATETIME)。基表是“calls”,我有一个“calls_participants”和一个“calls_other_data”。所有的表还有一个 call_id CHAR(36) 列来标识一个调用,所以它当然应该被索引。

我要存储很多行(10 亿),如果可能的话想节省空间和维护成本,所以我的想法是只在基表上索引 call_id 列,所以其他表不会具有除 CLUSTERED start_time 索引之外的任何索引。 然后,如果我必须根据 call_id 访问 call_other_data 表中的一行,我会写如下内容:

SELECT cod.some_column
FROM calls_other_data cod
WHERE cod.start_time = (SELECT start_time 
                        FROM calls 
                        WHERE call_id = '36-chars-unique-value')
  AND cod.call_id = '36-chars-unique-value'

我会说这个查询的性能与在 calls_other_data.call_id 上有一个索引完全一样,因为 calls.call_id 索引可以以相同的方式使用:start_time 值是自动包含的,所以SQL Server 必须执行相同的步骤:

  1. (either table).call_id 上查找索引以获取start_time
  2. calls_other_data.start_time 上的聚集索引查找

我只是从来没有读过这样的设计,想看看其他人对此的看法:) 你知道有什么缺点吗?

显然,如果调用表中缺少一行,则很难在其他表中查找它,但我不介意。

谢谢:)

【问题讨论】:

  • 这似乎很危险。如果两个电话同时开始怎么办?我认为呼叫的唯一标识符比跨表共享start_time 更有用。
  • 可能你的 start_time 不是 unique 所以这不是一个好键
  • 这就是为什么我要过滤 start_time 和 call_id。
  • 这可能更适合 Code Review Stack Exchange,因为它提供了解决方案并征求意见。

标签: sql sql-server database-design


【解决方案1】:

我明白你想表达什么。 calls_other_data 仍然会同时包含 call_id 列和 start_time 列,就像 calls 表一样,但 calls_other_date.call_id 列不会被索引,因为索引会带来存储成本。这似乎是你的想法。

这里需要注意的是,由于您的聚簇索引在您的任何表上都不是唯一的,sql 将通过添加一些称为uniqueifier 的额外数据使其唯一。因此,您在这里已经有了可能没有考虑过的额外存储空间,这让您尝试“优化”存储空间变得毫无意义。

我建议不要使用这种方法。存储很便宜,唯一索引对优化器有很大帮助,并且外键列(或类似外键的列,如果您实际上没有任何引用完整性)上的索引是一个很好的经验法则。

【讨论】:

  • 请注意,只有在发生冲突时才会添加额外的唯一标识符。但是为了唯一性,我会考虑将 call_id 作为第二列添加到聚集索引中。谢谢:)
猜你喜欢
  • 2022-12-29
  • 2015-10-13
  • 2011-08-21
  • 2011-06-04
  • 2012-08-05
  • 2011-07-26
  • 2012-08-26
  • 1970-01-01
  • 2011-08-13
相关资源
最近更新 更多