【问题标题】:SQL Server Clustered Index on Non-Unique Column非唯一列上的 SQL Server 聚集索引
【发布时间】:2016-09-14 12:22:54
【问题描述】:

我一直在尝试了解如何使用聚集索引来提高查询性能。

基本上,我有一个“消息”表,用于聊天应用程序。当用户打开聊天时,我们会根据用户正在与之交谈的客户从表格中读取消息历史记录。

消息表由以下列构成:

Id : CustomerId : 内容

表上最常使用的查询类似于

SELECT * FROM Message WHERE CustomerId = @CustomerId

我的问题是,CustomerId 列是否适合作为聚集索引的候选者?另外,鉴于 ID 字段是主键,SQL Server 是否仍需要“唯一化”聚集索引?

表格在选择和插入方面都会很重。

【问题讨论】:

    标签: sql sql-server clustered-index


    【解决方案1】:

    聚集索引不需要唯一,所以可以。

    但是,问题在于每次插入新消息时,SQL Server 都需要为同一客户的其他行旁边的新行找到一个空间。这通常效率低下,因为需要拆分页面,从而导致许多页面半满。而且,如果您在行上也有删除,事情会变得更加复杂。

    有多种选择。在繁忙的数据库中,您可以在页面上为其他插入留出空间。或者,另一种选择是根据客户 ID 对表进行分区。这一切都取决于。

    在大多数情况下,消息表上的标识列将是主键和聚集键。客户表上的附加索引就足够了。但是,在某些情况下,肯定有可以更好地工作的替代结构。

    【讨论】:

      【解决方案2】:

      在已经存在主键约束的键上添加聚集索引是不必要的重复。相反,主键约束也应该是聚集索引。但是,您的问题实际上是不同的...

      CustomerId 列是否适合聚集索引?

      如果不知道您将如何查询表,就无法回答这个问题。对于许多查询模式,该组织不是是最佳的(典型的例子是时间列是适当的聚集键的时间序列)。并且有同样多的查询示例最好的聚集索引。无法回答。

      鉴于 ID 字段是主键,SQL Server 是否仍需要“唯一化”聚集索引?

      如果索引不是声明的唯一的,那么 SQL Server 将添加唯一性列。但是,列 value 永远不会实现,因为永远不会发生重复。

      我有一个“消息”表,用于聊天应用程序...WHERE CustomerId = @Id ... ID 字段是主键

      请原谅,但这没有任何意义。您的意思是Messages每个客户只能有一条消息。那将是一个可怕的聊天体验。我很确定你的解释是错误的。

      我希望在CustomerId 上有一个带有聚集索引和主键约束的Customers 表。 Messages 表可能由 聊天室 或与聊天参与者配对的其他组组织组织。如果聊天总是在一位且恰好一位客户和一位代表之间进行,那么“聊天室”可能就是客户本身。无论如何,对此类Messages 表的典型查询将希望聊天室中交换的所有消息,按照发布的顺序与客户交换的所有消息,在订单发布。实际上,这是一个分区时间序列,最好由像 (chat_id, post_time)(customer_id, post_time) 这样的聚集索引提供服务。请注意,这不是主键,该表很可能有一个message_id 作为主键,但不是集群的。

      【讨论】:

      • @GordonLinoff 提出了一个有效的观点,即像 (chat_id, post_time) 这样的聚集键会在索引中的多个点插入数据时导致碎片,但根据我的经验,when它成为一个问题,可以通过简单的重组或重建(最终使用低填充因子)来解决。相反,选择一个聚集索引来确保物理组织的仅在末尾附加语义并在此过程中惩罚查询通常要糟糕得多。
      • '@Id' 应该是作为传递给存储过程的参数的客户 ID。因此,您将通过其 ID 查找客户的所有消息。这是一个写得很糟糕的例子。是的,在这种情况下,“客户 ID”基本上是聊天室标识符。
      猜你喜欢
      • 1970-01-01
      • 2010-10-23
      • 2011-05-29
      • 2014-01-08
      • 2011-11-30
      • 2012-10-01
      • 1970-01-01
      相关资源
      最近更新 更多