分区表上复合聚簇主键的列顺序?

u23*_*534 6 sql-server-2008 sql-server partitioning

我有下表。

create table T (K1 date, K2 int references S(Id), ....) on partitionScheme(K1)
Run Code Online (Sandbox Code Playgroud)

该表将按 K1 进行分区(K1 具有低选择性。数据将按顺序追加K1)。首选以下哪个主键(列顺序不同)?

alter table T add primary key clustered (K1, K2)
alter table T add primary key clustered (K2, K1)
Run Code Online (Sandbox Code Playgroud)

或者PK应该是非聚集的并创建另一个聚集索引?

很多查询看起来像:

select ....
from T join S on S.Id = T.K2
where ....
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 7

首选以下哪个主键(列顺序不同)?

与所有索引决策一样,很大程度上取决于查询表的方式。

所有分区索引(对于 SQL Server 2008 及更高版本)都有分区 ID(不是分区键值)作为每个分区索引中的隐藏前导键列,因此有效的竞争定义是:

分区ID、K1、K2
对比
分区ID、K2、K1

正如人们所料,这会影响每个索引对不同类型查询的效用。主要的额外考虑是仍然支持对第一个实键(K1 或 K2)的不等式查找,而不管PartitionID列上的任何不等式查找和/或分区消除操作。

例如,(K1, K2) 索引规范可以同时寻找一系列分区和一系列 K1 值:

SELECT T1.* 
FROM dbo.T1 AS T1
WHERE 1 = 1
AND T1.K1 >= CONVERT(date, '20080711', 112)
AND T1.K1 <= CONVERT(date, '20100711', 112);
Run Code Online (Sandbox Code Playgroud)

多层次不平等寻求

以 (K2, K1) 作为聚集索引键的表上的相同查询可以寻找分区范围,但它必须完全扫描每个符合条件的分区以定位与 K1 谓词完全匹配的行。需要明确的是,K1 值的测试将作为残差谓词应用,而不是作为搜索操作。

这将在 showplan 中显示为聚集索引扫描,具有分区消除查找和 K1 值的残差谓词:

带有残差谓词的分区消除扫描

使用日期数据类型作为分区键时的一个微妙之处是,如果您希望可靠地进行分区消除,则必须小心在查询中使用显式日期类型。使用其他类型,例如datetime,很容易(偶然)完成,但通常会阻止消除,这是合乎逻辑的预期。

例如,此查询将涉及所有分区:

DECLARE @dt datetime = '20080711';

SELECT * 
FROM dbo.T1 AS T1
WHERE T1.K1 = @dt;
Run Code Online (Sandbox Code Playgroud)

而这个查询只会涉及一个分区:

DECLARE @dt date = '20080711';

SELECT * 
FROM dbo.T1 AS T1
WHERE T1.K1 = @dt;
Run Code Online (Sandbox Code Playgroud)

两个查询在图形显示计划(聚集索引查找)中看起来表面上相同。您需要详细检查运算符属性以检查是否正在应用静态或动态分区消除。

对于问题中给出的示例连接查询:两种索引策略都包含 K2 列,但通常都不能在没有排序的情况下以 K2 顺序提供行。因此,任一索引对于散列连接或嵌套循环连接都同样适用,但都不能提供 K2 上的合并连接所需的输入顺序。

这对于 (K2, K1) 索引来说似乎有悖常理,但请记住前导PartitionID键。每个分区都有 (K2, K1) 顺序的行。除非在查询中只指定了一个分区,否则需要进行排序以按 K2 顺序返回行。(K1, K2) 索引只能为单个分区K1 的单个给定值返回按 K2 顺序排列的行。

如果在插入操作期间附加数据实际上按集群键排序,则建议的集群主键(K1、K2)具有最小化基表页面拆分的潜在优势。对于 (K1, K2) 索引,这意味着按 (PartitionID, K1, K2) 排序的行。对于 (K2, K1),它将是 (PartitionID, K2, K1)。

相关阅读:分区表和索引的查询处理增强


Ken*_*her 5

由于您正在使主键聚簇,如果您查看这篇Technet 文章关于将索引与分区对齐,它在聚簇索引部分中提到,如果您不在聚簇索引中包含分区列,它将为您完成。您的两个选项都包含分区列,因此这不是问题,但应该牢记。

所有这些都说了我读过的所有内容都没有说只要聚集索引包含分区列(使其对齐),它就会产生任何区别。就个人而言,我可能会将分区列放在首位。在我看来,这似乎允许 SQL 在查看索引中的任何其他列之前决定要查看的分区。

根据给出的信息,在这种情况下没有真正需要单独的 PK 和 CIX。这当然假设 K1、K2 的组合是唯一的。