非唯一聚集索引管理

pan*_*kos 3 performance index sql-server fragmentation sql-server-2016

我最近被指派管理 SQL Server 2016 中的数据库,我发现数据库中有许多表具有非唯一聚集索引,导致非聚集主键索引。

我知道上述显然是允许的,但并不理想(特别是对于大表),也许在某些情况下,这是有道理的,但此类表的数量告诉我,这更像是粗心的表定义的结果。

例如,一个名为的表Transaction将有一个带有以下键的聚集索引:date, is_deleted. 此外,该表将在名为 的列上有一个非聚集主键id

现在,其中一些表非常大,并且上面有许多外键引用,所以我想出了以下步骤,在 Aaron 在此线程中的回答的帮助下更改所有这些表无法删除非 PK 索引,因为它是在外键约束中引用

  1. 删除表的聚集索引
  2. 删除所有引用该表的外键约束
  3. 删除表的当前主键约束
  4. 使用id列创建主键集群约束
  5. 创建之前删除的所有外键约束
  6. 可选 - 创建以前的聚集索引作为非聚集索引

我知道对于大表,我需要找到一个维护窗口来执行更改,但是您是否发现上述解决方案有任何我没有想到的问题或陷阱?这种方法会导致非聚集索引的其余部分出现碎片吗?

涉及很多表,我想确保我不会触发任何副作用。

Tom*_*m V 7

如果不知道您的查询模式,就很难回答这个问题,但是在删除所有聚集索引并用其他东西替换它们时,您肯定会产生副作用。

我也不认为您假设拥有非唯一聚集索引是草率的表设计或根据定义是次优的,这不一定是正确的。

添加非唯一聚集索引时,uniqueifier 如果键中有重复值,SQL Server 将向索引添加 4 字节以确保该键是唯一的。计算这个唯一标识符会增加一些开销,但不会太戏剧化。这个唯一标识符也必须在非聚集索引中,因为索引书签必须指向单行。

另一方面,根据情况,您给出的示例可能是一个很好的聚集索引:

例如,名为 Transaction 的表将有一个带有以下键的聚集索引:date、is_deleted。此外,该表将在 id 列上有一个非聚集主键。

如果在同一日期有很多事务,并且几乎每个查询都是一个 SELECT * FROM transactiontable WHERE date = <somedate> AND is_deleted=0.

如果必须使用非聚集索引并求助于键查找,这样的查询可能会受到严重伤害。

不可能说你会触发什么副作用,但你肯定会触发一些,而你这样做的原因可能是错误的。

如果您坚持这样做,请确保首先在测试环境中对其进行测试,如果您这样做了,您应该能够判断此方法是否有效以及它是否会导致碎片化(但这可能是您的担心)。

  • @panikkos,您不仅需要单独评估每个案例,还需要使用代表性查询进行测试。补充一下@TomV 所说的,有序聚集有序扫描可以为`ORDER BY` 子句提供序列,并且只有在键值不是唯一的时候才会添加唯一标识符。如果查询按日期排序,那 556,852 次扫描可能会变成 556,852 次排序运算符,而没有日期的 CI。并不是说替代 CI 不是更好,只是现有的 CI 看起来是经过深思熟虑而不是粗心选择的。一不小心,所有聚集索引都将成为主键。 (3认同)