我在SQL Server 2008 R2中工作
作为完整架构重建的一部分,我正在创建一个表格,用于按日期按邮政编码存储广告活动的效果。我正在考虑的表格设置是这样的:
CREATE TABLE [dbo].[Zip_Perf_by_Day] (
[CampaignID] int NOT NULL,
[ZipCode] int NOT NULL,
[ReportDate] date NOT NULL,
[PerformanceMetric1] int NOT NULL,
[PerformanceMetric2] int NOT NULL,
[PerformanceMetric3] int NOT NULL,
and so on... )
现在,CampaignID,ZipCode和ReportDate的组合是一个完美的自然键,它们唯一地标识单个实体,并且对于相同的值组合,不应该有2条记录。此外,几乎所有对此表的查询都将在这3列中的一个或多个上进行过滤。但是,在考虑此表的聚集索引时,我遇到了一个问题。这3列不会随时间增加。 ReportDate没问题,但在插入行时,CampaignID和Zipcode将会遍布整个地方。我甚至无法提前订购,因为结果来自不同来源,因此CampaignID 50000的数据可能会在上午10点插入,CampaignID 30000可能会在下午2点进入。如果我使用PK作为我的聚集索引,我将遇到碎片问题。
所以我认为我需要一个身份ID列,我们称之为PerformanceID。我看不出在任何查询的select list或where子句中我都会使用PerformanceID的情况。我应该使用PerformanceID作为我的PK和聚簇索引,然后在CampaignID,ZipCode和ReportDate上设置唯一约束和非聚集索引吗?我应该保留这3列作为我的PK并且只在PerformanceID上有我的聚集索引吗? (< - 这是我现在倾向于的选项)是否可以有一个稍微碎片的表?还有其他选择我没有考虑过吗?我正在寻找什么能给我最好的读取性能,同时不会完全破坏写入性能。
一些实际使用信息。该表将分批编写。 Feed在白天的不同时间进入,它们被处理,并且这个表被写入。它会被大量阅读,因为今天的表现非常重要。填写此表时,它应该有大约500万行,并且将以每天约8,000 - 10,000行的速度增长。
答案 0 :(得分:3)
根据我的经验,您可能确实希望使用另一个INT Identity
字段作为聚簇索引键。我还要为那个添加UNIQUE
约束(它有助于执行计划)。
原因很大一部分是空间 - 如果对聚簇索引使用3字段键,那么在该表上的每个非聚集索引的每一行中都将包含所有3个字段(作为聚簇索引行标识符) 。如果你只打算有几个索引并不是什么大不了的事,但是如果你有很多索引它可以产生很大的不同。每行数据越多,所需的页面越多,IO越多。
碎片是一个非常真实的问题,可能会导致严重的性能问题,尤其是随着表的增长。
拥有额外的群集密钥也意味着您的插入更快。所有新行都将转到表的末尾,这意味着不会触及或重新排列现有行。
如果你想在其他表中使用这三个字段作为FK,那么无论如何都要将它们作为你的PK。
在大多数情况下,如果您直接引用聚簇索引键并不重要。只要它是狭窄的,增加的和独特的,你就应该保持良好状态。
修改强>
正如Damien在评论中指出的那样,如果你要过滤PK的单个字段,你需要在每个字段上都有一个索引(或者总是使用覆盖索引中的第一个字段)。
答案 1 :(得分:2)
对于给定的信息(ReportDate,CampaignID,ZipCode)或(ReportDate,ZipCode,CampaignID),似乎比代理键更适合聚簇索引。如果重建索引所花费的时间变得令人望而却步,那么碎片整理将是一个潜在的问题,但考虑到我希望这个表的大小(10s或1000s而不是每天1,000,000s行),这似乎不太可能是一个问题。
答案 2 :(得分:1)
如果我理解你所写的所有内容,那么由于碎片惩罚,你选择退出自然聚类。
为此,您需要考虑无意义的ID :
没有什么可以击败一个好的测试案例 - 所以最后这是我能给出的最佳建议。
使用数据库,构建脚本通常相对容易,这些脚本将创建具有实际工作负载和实际数据量的真实基准。