繁体   English   中英

SQL Server - 分区表与聚簇索引?

[英]SQL Server - Partitioned Tables vs. Clustered Index?

假设您有一个包含三列的大型表,如下所示:

[id] INT NOT NULL,

[date] SMALLDATETIME NOT NULL,

[sales] FLOAT NULL

还假设您仅限于一个物理磁盘和一个文件组(PRIMARY)。 您希望此表能够在100个日期(10,000个以上的记录)中保持10,000,000+ ID的销售额。

与许多数据仓库方案一样,数据通常按日期顺序增长(即,每次执行数据加载时,您将插入新日期,并可能更新一些最近的数据日期)。 出于分析目的,通常会查询和聚合数据,以便随机设置~10,000个ID,这些ID将通过与另一个表的连接来指定。 通常,这些查询不指定日期范围,或指定非常宽的日期范围,这引出了我的问题:索引/分区此表的最佳方法是什么?

我已经考虑了一段时间了,但我遇到了相互矛盾的解决方案:

选项#1:由于数据将按日期顺序加载,请将聚集索引(和主键)定义为[date],[id]。 还可以在日期创建“滑动窗口”分区功能/方案,允许新数据快速移入/移出表格。 可以在id上创建非聚集索引以帮助查询。

预期结果#1:这种设置对于数据加载来说非常快,但在分析读取方面是次优的,在最坏的情况下(不受日期限制,不满意查询的id集),100%可以读取数据页面。

选项#2:由于一次只查询一小部分id的数据,因此将聚簇索引(和主键)定义为[id],[date]。 不要费心去创建分区表。

预期结果#2:在加载数据时预计会有巨大的性能损失,因为我们无法再按照日期快速限制。 对于我的分析查询,预计会有巨大的性能优势,因为它可以最大限度地减少读取的数据页数。

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

预期结果#3:不确定会发生什么。 鉴于聚集索引中的第一列是[id],因此(这是我的理解)数据按ID排列,我希望我的分析查询具有良好的性能。 但是,数据按日期划分,这与聚簇索引的定义相反(但仍然对齐为日期是索引的一部分)。 我没有找到很多与这种情况有关的文档,以及我可以从中获得的性能优势(如果有的话),这使我得到了最终的奖金问题:

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

这张桌子非常窄。 如果真实表格会变窄,您应该乐于进行表扫描而不是索引 - >查找。

我会这样做:

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)

它使用搜索和宽范围查询处理点查询,并根据日期条件和id标准进行有限扫描。 索引中没有每条记录的查找。 是的,我把写入时间(和使用的空间)增加了一倍,但这很好,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.

可以按名称在查询中使用聚簇视图,或者在FROM和WHERE子句适当时,优化器将选择使用聚簇视图。 例如,此查询将使用群集视图。 请注意,查询中引用了基表。

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

通过索引 ,您可以方便地访问特定列...“ 聚集”视图使您可以方便地访问特定行。

在对I / O进行本地化时,聚簇索引将为查询提供性能优势。 日期是传统的分区策略,因为许多D / W查询按日期查看移动。

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

在不同的分析工作负载上看到聚集索引可以获得很多性能提升,这有点不寻常。 查询优化器将使用一种称为“索引交集”的技术来选择行,甚至不会访问事实表。 请参阅这里 ,我在另一个问题上做了一个帖子,通过一些链接更深入地解释了这个问题。 聚簇索引可能会也可能不会参与索引交集,因此您可能会发现它在一般查询工作负载上获得的收益相对较少。

您可能会发现加载的情况,聚集索引会为您带来一些好处,特别是如果您已经在ETL过程中计算得到的计算(例如获得的溢价 )。 在这种情况下,您可能会获得一些好处。 如果您有一个特定的查询,您知道它将一直执行,为此使用聚簇索引可能是有意义的。 如果您希望此类查询成为应用程序完成的绝大部分工作,则选项#2和#3将对您有显着的益处。

对于一个灵活的系统,一个带有ID索引的简单日期范围分区(如果分区保持一个范围,那么日期可能会让你获得与任何分区一样好的性能。你可能会从索引限制情况的集群中获得一些好处。你可能会通过在数据上构建多维数据集并确保为此查询正确设置聚合,也可以获得一些里程。

如果您在select语句中使用分区,那么您可以获得一些速度。

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

关于你原来的问题:我建议你选择#1,其中包含id的非聚集索引。

我会做以下事情:

  • [Id]上的非聚集索引
  • [日期]上的聚类索引
  • 将[sales]数据类型转换为numeric而不是float

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

如果您的插入插入速度比日期时间分辨率为3.33 ms更快,则日期列上的聚簇索引不是很好。 如果你这样做,你将获得具有相同值的2个密钥,并且你的索引必须得到另一个内部uniquifier,这将增加它的大小。

我会选择你的2号选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM