【问题标题】:Partitioning in SQL Server Standard Edition with billion of rows在 SQL Server Standard Edition 中使用数十亿行进行分区
【发布时间】:2015-02-14 05:29:39
【问题描述】:

您好想问一下如何分区下表(见下文)。我遇到的问题不在于检索由聚集索引解决的历史记录。但正如您所见,索引是基于 HistoryParameterID 然后是 TimeStamp,这是必需的,因为行的检索基于上述列。

这里的问题是,每当它达到约 10 亿条记录时,插入速度就会减慢,因为场景是要插入 15k 行\秒(注意这可以是 30k - 100k),并且每行对应于一个历史参数 ID。

基本上,HistoryParameterID 不是唯一的,它与下表的其他列有一个 -> 多的关系。

我的直觉是,由于索引,它会减慢插入速度,因为插入并不总是在底部,因为它是由 HistoryParameterID 排列的。

我使用时间戳作为索引进行了一些测试,但由于查询性能不可接受,因此无济于事。

有没有办法通过历史 ParameterID 进行分区?我正在尝试,所以我为分区视图创建了 15k 个表。但是当我创建视图时它没有完成执行。有小费吗?或者有什么方法可以分区?请注意,我使用的是标准版,不能使用企业版。

CREATE TABLE [dbo].[HistorySampleValues]
(
    [HistoryParameterID] [int] NOT NULL,
    [SourceTimeStamp] [datetime2](7) NOT NULL,
    [ArchiveTimestamp] [datetime2](7) NOT NULL CONSTRAINT [DF__HistorySa__Archi__2A164134]  DEFAULT (getutcdate()),
    [ValueStatus] [int] NOT NULL,
    [ArchiveStatus] [int] NOT NULL,
    [IntegerValue] [bigint] SPARSE  NULL,
    [DoubleValue] [float] SPARSE  NULL,
    [StringValue] [varchar](100) SPARSE  NULL,
    [EnumNamedSetName] [varchar](100) SPARSE  NULL,
    [EnumNumericValue] [int] SPARSE  NULL,
    [EnumTextualValue] [varchar](256) SPARSE  NULL
) ON [PRIMARY]

CREATE CLUSTERED INDEX [Source_HistParameterID_Index] ON [dbo].[HistorySampleValues]
(
    [HistoryParameterID] ASC,
    [SourceTimeStamp] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

【问题讨论】:

  • 那不是几百万行吗?
  • 十亿行,分配到 15k 个参数 ID

标签: sql-server scalability


【解决方案1】:

我正在尝试,所以我为分区视图创建了 15k 表。但当 我创建了它没有完成执行的视图。有小费吗?或者在那里 有什么办法分区吗?请注意,我使用的是标准版和 不能使用企业版。

如果您沿着分区视图路径 (http://technet.microsoft.com/en-us/library/ms190019.aspx),我建议减少表(少于 100 个)。如果没有分区表,优化器必须进行大量工作,因为视图的每个表都可能有不同的索引。

如果 HistoryParameterID 是增量的,我不希望插入会随着表大小而变慢。但是,在随机值的情况下,由于缓冲区缓存效率较低,插入将随着表大小的增长而逐渐变慢。该问题将存在于单个表、分区表或分区视图中。有关使用 guid 的示例,请参阅 http://www.dbdelta.com/improving-uniqueidentifier-performance/,但该问题适用于任何随机键值。

您可以尝试使用 SourceTimestamp 单独作为聚集索引键和 HistoryID 和 SourceTimestamp 上的非聚集索引的单个表。这将提供最佳的插入性能,并且非聚集索引(可能包含包含的列)可能足以满足您的选择查询。

【讨论】:

  • 顺便说一句,HistoryParameterID 不是增量的,因此基本上它是一个随机值,具体取决于 0-15k、0-30k 和高达 0-100k 的场景。好的,会有帮助吗?在插入性能中将 SourceTimestamp 作为聚集索引和 HistoryId 和 SOURceTimestamp 上的非聚集索引?同时保持查询性能?
  • 那么我需要更改我的查询吗?因为当前它是 Select .... from Table where HistoryParameterID = paramId AND SourceTimeStamp>= starttime and SOurceTimestamp
  • SourceTimestamp 上的聚集索引将有助于插入性能。至于查询性能,如果查询请求,将需要额外的键查找来检索除 SourceTimestamp 和 HistoryID 之外的列。这将增加更多开销,但我不能说性能是否足够。很大程度上取决于触摸和返回的行数。
  • 鉴于此处的脚本 Select .... from Table where HistoryParameterID = paramId AND SourceTimeStamp>= starttime 和 SOURceTimestamp
  • 这是 10 亿行表大小的一小部分,因此我希望非聚集索引查找和键查找返回 15K 行。无论表大小如何,我都希望性能保持一致,最坏的情况是每个 SELECT 大约 15K 物理读取。很大程度上取决于磁盘子系统的性能。
【解决方案2】:

您需要的一切都在这里。我希望你能弄清楚。

http://msdn.microsoft.com/en-us/library/ms188730.aspx

对于标准版,存在类似this 答案的替代解决方案。

this 也是一篇有趣的文章。

我们还在我们的企业自动化应用程序中通过围绕用户表的自定义索引来实现这一点,并且效果很好。

以下是自定义实现的优缺点:

优点:

  • 由于应用程序的逻辑感知,分区表的性能更高。

缺点:

  • 实现路由方法和更新索引。

  • 非集中式数据。

【讨论】:

  • 您好,问题是我使用的是 SQL SErver 标准版,企业可以使用分区表
  • 更新了问题以指定 SQL Server 标准版是唯一的选择
  • 嗨,TommyMore,感谢您的反馈,我们将对其进行调查。我希望分区视图能解决问题,但创建 15k 联合,因为我会将它分解为 15k 表,它在创建视图时失败
  • 有什么方法可以对上面的表进行分区,以便我的索引位于 SourceTimeStamp 上?
  • 是的,像我们一样实现分布式服务器或您选择的“表”,并在您的应用程序中分离索引业务,然后根据 SourceTimeStamp 的自定义索引实现路由您的应用程序的请求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多