复合群集PK行为与非群集PK +非唯一聚簇索引

时间:2013-04-17 21:26:31

标签: sql sql-server database-design

我有一个包含几列的表,其中两个重要的是appid和fileid。他们一起组成了桌上的PK。该表的典型用例是包含appid x的文件数量,或者哪个appid最受欢迎。这些查询也将仅在文件的子集上运行,而不是所有文件。这两列都不是唯一的。

基于此,我觉得聚集索引的最佳选择是AppId。但是,由于将两列设置为PK会产生额外的非聚集索引,并且appids缺乏唯一性(会有很多重复)意味着它无论如何都需要在幕后使用uniquifier列,只是说它更有意义PK是聚簇的,而不是指定另一个聚簇索引?假设我在PK中首先指定了AppId,它会像在幕后使用uniquifier一样处理diagnosticfileid并以这种方式给出最佳性能吗?

编辑:我忘了最初提到的一个重要的事情是,APPId不会稳定增加或任何东西,因此会在表格的中间插入。我想我可以通过使用fillfactor来防止这个问题,但是表格会变得很大,所以我不知道这会有多大帮助。

此外,它会经常插入,但一次不会插入大块。可能像一小时几千行。在这方面,实际上没有任何值可靠地增加并成为聚簇索引的良好选择,但我不确定这是多么大的交易。我可以添加一个id只是为了有一个很好的值来聚集,但我觉得那个慢下来选择了很多。

2 个答案:

答案 0 :(得分:3)

如果您最常见的两个问题是“有多少文件包含appId”和“哪个appId最受欢迎”,那么您应该制作这个索引视图:

CREATE VIEW
        v_appCount
WITH SCHEMABINDING
AS
        SELECT  appId, COUNT_BIG(*) AS cnt
        FROM    dbo.mytable
        GROUP BY
                appId
GO

CREATE UNIQUE CLUSTERED INDEX
        ux_v_appCount_appId
ON      v_appCount (appId)

这样您就可以运行这些查询:

SELECT  cnt
FROM    v_appCount
WHERE   appId = @myAppId

SELECT  TOP 100
        *
FROM    v_appCount va
ORDER BY
        appId DESC

几乎立即。

答案 1 :(得分:1)

复合PK的问题是,如果它们是聚簇的,因为表中间的插入会导致内容的物理重新排序。如果表格不会达到巨大的尺寸,那么它可能无关紧要,但绝对值得考虑。我应该补充一点,如果这是一个高选择表和一个低插入表,那么这也限制了插入在主键中间的影响。你绝对可以使它成为非群集主键,但这有选择性能方面的考虑。

修改
考虑到你的编辑,我建议你做一个自动递增PK(非聚集)并创建一个唯一约束(它也创建一个唯一的,非聚集索引)。基本上,我不建议在此表上使用聚簇索引。如果没有它,我认为你会看到很多性能差异,但如果它存在,你就会在表格中间进行数千次插入。死锁会困扰你。

快速阅读this article。虽然它已经陈旧,但原则仍然适用。