2008-09-23 133 views
15

让我们假设你有三列一个巨大的表,如下图所示:SQL Server - 分区表与集群索引?

[id] INT NOT NULL, 

[date] SMALLDATETIME NOT NULL, 

[sales] FLOAT NULL 

还假定您仅限于一个物理磁盘和一个文件组(主)。您预计此表在100个日期(容易1B +记录)中保持10,000,000个ID以上的销售额。与许多数据仓库场景一样,数据通常会按日期顺序增长(即,每次执行数据加载时,您将插入新日期,并且可能会更新某些更新的数据日期)。出于分析目的,数据通常会被随机查询并汇总到〜10,000个id,这些id将通过与另一个表的联接来指定。通常,这些查询不指定日期范围,或者指定非常宽的日期范围,这引起我的问​​题:索引/分区此表的最佳方法是什么?

我已经想了一段时间,但是卡具有冲突的解决方案:

选项#1:随着数据将依次被日期被加载,定义群集索引(和主键)作为[日期],[id]。还可以在日期上创建“滑动窗口”分区功能/方案,以便将新数据快速移入/移出表格。有可能在ID上创建非聚集索引以帮助查询。

预期的结果#1:这种设置会非常快的数据加载的目的,但次优的,当涉及到分析原文,在最坏的情况下(不受日期限制,不吉利与集ID的的查询),可以读取100%的数据页面。

选项2:由于数据一次只能查询一小部分ids,因此将聚集索引(和主键)定义为[id],[date]。不要打扰创建分区表。

预期结果#2:由于我们无法再按日期快速限制,因此在加载数据时预期会有巨大的表现。当涉及到我的分析查询时,预计会带来巨大的性能收益,因为它可以最大限度地减少读取的数据页的数量。

选项#3:集群(和主键)如下:[id],[date]; “滑动窗口”分区功能/方案日期。

预期结果#3:不知道该期待什么。考虑到聚集索引中的第一列是[id],因此(这是我的理解)数据是按ID排列的,我希望我的分析查询具有良好的性能。但是,数据按日期进行分区,这与聚簇索引的定义相反(但仍与日期成为索引的一部分对齐)。我还没有找到很多说明这种情况的文档以及我可能从中获得哪些性能优势,这会带来我最终的奖金问题:

如果我在一个文件组上创建表一个磁盘,在一列上有一个聚簇索引,在同一列上定义一个分区会带来什么好处(加载数据时除了分区切换)?

回答

0

如果你在select语句中使用分区,那么你的cn获得了一定的速度。

如果你不使用它,只使用“标准”选择,那么你没有任何好处。

在你原来的问题:我会建议你选项#1与包括id的非聚集索引。

3

当本地化I/O时,聚簇索引会为查询带来性能优势。 Date是传统的分区策略,因为许多D/W查询按日期查看运动。

分区表的经验法则表明分区大小应该在10米左右。

从多样化分析工作负载的聚集索引中看到很多性能增益会有点不寻常。查询优化器将使用一种名为'Index Intersection'的技术来选择行,而不会触及事实表。查看Here了解我在另一个问题上所做的文章,该文章通过一些链接更深入地解释了这一问题。 聚集索引可能参与也可能不参与索引交集,因此您可能会发现它在一般查询工作负载上获得的相对较少。

您可能会发现聚集索引为您带来一些收益的情况,特别是如果您有在ETL过程中计算的派生计算(例如Earned Premium)。在这种情况下,您可能会获得一些好处。如果你有一个特定的查询,你知道它会一直执行,为此使用聚簇索引是有意义的。如果您希望这种类型的查询成为应用程序完成的绝大多数工作,则选项#2和#3只会对您有很大的好处。

对于一个灵活的系统,一个带有ID索引的简单日期范围分区(如果分区拥有一个范围,那么日期可能会让你获得与任何其他性能相当的性能,你可能从集群索引受限。情况下,您也可以从建立多维数据集在数据和确保聚合针对此查询正确设置得到一些里程

0

我会做到以下几点:。

  • 非聚集的索引[ Id]
  • [日期]上的聚集索引
  • 将[销售]数据类型转换为数字而不是浮点数
+0

你最后一点很有趣。从float转换为numeric会带来什么样的性能好处? – 2008-09-23 13:42:40

+1

您可以更准确地了解您正在存储的数据,并且数字数据类型是精确数字,其中浮点数是近似数字。 – GateKiller 2008-09-23 18:04:46

7

此表非常窄。如果真正的表格会很窄,那么你应该乐意使用表扫描而不是索引 - >查找。

我这样做:

CREATE TABLE Narrow 
(
    [id] INT NOT NULL, 
    [date] SMALLDATETIME NOT NULL, 
    [sales] FLOAT NULL, 
    PRIMARY KEY(id, date) --EDIT, just noticed your id is not unique. 
) 

CREATE INDEX CoveringNarrow ON Narrow(date, id, sales) 

该处理点查询与寻求与对日期的标准和标识的标准扫描有限范围广泛的查询。没有索引的每条记录查找。是的,我已经将写入时间加倍(和使用的空间),但这很好,imo。


如果有一些需要特定的数据块(这需要的是通过剖析 !!证明),我想创建一个集群视图靶向表的那个部分。

CREATE VIEW Narrow200801 
AS 
SELECT * FROM Narrow WHERE '2008-01-01' <= [date] AND [date] < '2008-02-01' 
--There is some command that I don't have at my finger tips to make this a clustered view. 

集群意见,可以在查询中通过名称来使用,或者优化器将选择使用WHERE子句是适当的群集意见时,FROM和。例如,这个查询将使用聚集视图。请注意,查询中引用了基表。

SELECT SUM(sales) FROM Narrow WHERE '2008-01-01' <= [date] AND [date] < '2008-02-01' 

由于指数让你做特定的列方便到达... 集群视图让你做特定的行方便到达。

0

按日期对表进行分区。多个水平分区将比具有多行的一个大表更具性能。

0

如果插入的日期时间分辨率为3.33毫秒,插入将会更快地插入日期列中的聚集索引不好。 如果你这样做,你会得到2个具有相同值的键,你的索引将不得不得到另一个内部的uniquifier,这将增加它的大小。

我会去#2的选项。