非唯一列上的SQL Server聚簇索引

时间:2016-09-14 12:22:55

标签: sql sql-server clustered-index

我一直在尝试阅读使用聚簇索引作为提高查询性能的方法。

基本上,我有一个'Messages'表,用于聊天应用程序。当用户打开聊天时,我们会根据用户与之对话的客户从表中读取消息历史记录。

消息表由列组成:

ID:CustomerId:Content

表上最常用的查询类似于

SELECT * FROM Message WHERE CustomerId = @CustomerId

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

选择和插入的表格都很重。

2 个答案:

答案 0 :(得分:1)

聚集索引不需要是唯一的,因此可以。

但问题是,每次插入新邮件时,SQL Server都需要为同一客户的其他行旁边的新行查找空格。这通常效率低下,因为页面需要拆分,导致许多半填充页面。而且,如果您也删除了行,事情会变得更加复杂。

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

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

答案 1 :(得分:0)

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

  

CustomerId列是聚簇索引的合适候选者吗?

如果不知道你将如何查询表格,就无法回答这个问题。有许多查询模式,此组织是最佳的(典型示例是时间列,其中时间列是适当的聚簇键)。此 最佳聚簇索引的查询示例也很多。无法回答。

  

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

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

  

我有一条消息' table,在聊天应用程序中使用... WHERE CustomerId = @Id ... ID字段是主键

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

我希望在Customers上有一个CustomerId表,其中包含聚簇索引和主键约束。 Messages表可能由聊天室或其他与聊天参与者配对的组织组织。如果聊天始终在一个客户和一个代表之间,则聊天室'可能是客户本身。无论如何,这种Messages表的典型查询都希望在聊天室中交换的所有消息,按照发布的顺序与客户交换的所有消息,在发布的订单。实际上,这是一个分区时间序列,最好由聚类索引(如(chat_id, post_time)(customer_id, post_time))提供。请注意,这是不是主键,表可能有message_id作为主键,但非群集。