31亿行数据如何管理?

Cal*_*der 14 database-design sql-server

我目前的任务是为相对大量的数据实施存储模式。将主要访问数据以确定当前data point值,但我还需要跟踪过去六个月的历史数据趋势/分析。

加入最近要求跟踪min/ max/sum在过去的小时值。

注意:理想情况下,我想考虑 MongoDB 选项,但我需要先证明我已经用完了 SQL-Server 选项。

数据

下表表示主要数据源(最常查询)。该表将有大约 500 万行。数据更改将主要是初始数据加载后UPDATE非常偶然的INSERT语句。我选择了对数据进行聚类,dataPointId因为您将始终选择all values for a given data point.

// Simplified Table
CREATE TABLE [dbo].[DataPointValue](
    [dataPointId]  [int] NOT NULL,
    [valueId]      [int] NOT NULL,
    [timestamp]    [datetime] NOT NULL,
    [minimum]      [decimal](18, 0) NOT NULL,
    [hourMinimum]  [decimal](18, 0) NOT NULL,
    [current]      [decimal](18, 0) NOT NULL,
    [currentTrend] [decimal](18, 0) NOT NULL,
    [hourMaximum]  [decimal](18, 0) NOT NULL,
    [maximum]      [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointValue] PRIMARY KEY CLUSTERED ([dataPointId],[valueId])
)
Run Code Online (Sandbox Code Playgroud)

第二个表明显更大,大约有 31 亿行(代表过去六个月的数据)。超过六个月的数据将被清除;否则严格的数据INSERT语句(~200 行/秒,720,000 行/小时,1700 万行/周)。

// Simplified Table
CREATE TABLE [dbo].[DataPointValueHistory](
    [dataPointId] [int]            NOT NULL,
    [valueId]     [int]            NOT NULL,
    [timestamp]   [datetime]       NOT NULL,
    [value]       [decimal](18, 0) NOT NULL,
    [delta]       [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointHistory] PRIMARY KEY CLUSTERED ([dataPointId], [valueId], [timestamp])
Run Code Online (Sandbox Code Playgroud)

)

预期随着跟踪数据点值的数量增加到 400 行/秒(因此达到 ~ 100 亿并非不可能),该表的大小将增加一倍。

问题(是的,我问的不止一个……它们都密切相关)。

我目前使用的是 SQL-Server 2008 R2 标准版数据库。如果可以通过表分区获得所需的性能级别(或 MongoDB,如果无法使用 SQL-Server 达到所需的性能级别),我可能会考虑升级到企业版。我希望您对以下内容提出意见:


1) 鉴于我需要计算过去一小时的min,maxsum(如now - 60 minutes)。跟踪最近数据的最佳方法是什么:

  • 将最近的数据保存在数据服务的内存中。用每个数据更新写出计算的最小值/最大值/平均值。

  • 在每个 UPDATE 语句期间从历史记录表中查询最近的历史记录(影响下一个问题?)。查询将访问数据点值的最新数据,并且应该只扫描最后一百万条记录左右?

  • 将最近的历史记录存储在 DataPointValue 行本身以避免历史表查找?也许存储为分隔字符串并在 UPDATE 过程中处理?

  • 我还没有考虑过的其他选择?


2) 对于DataPointValueHistory,对数据的查询将始终由dataPointId和 一个或多个valueId's 进行。查询的数据通常是最后一天、一周或一个月的数据,但在某些情况下可能是整整六个月。

我目前正在生成一个示例数据集,以试验按 dataPointId/valueId/timeStamp 或 timeStamp/dataPointId/valueId 进行聚类是否更有意义。如果有人有处理这种尺寸的桌子的经验并愿意提供他们的见解,我们将不胜感激。我倾向于后一种选择以避免索引碎片,但查询性能至关重要。

  • 集群DataPointValueHistory由dataPointId - > VALUEID - >的timeStamp

  • 集群DataPointValueHistory通过时间戳- > dataPointId - > VALUEID


3)最后,如上所述,我认为对DataPointValueHistory表进行分区是有意义的。任何关于如何最好地划分历史数据的建议将不胜感激。

  • 如果首先按时间戳聚类,我认为数据应该按周进行分区(总共 27 个分区)。最早的分区将在第 27 周后被清除。

  • 如果首先按 dataPointId 聚类,我认为数据应该按 id 的某个模数进行分区?

由于我在表分区方面的经验非常有限,您的专业知识将不胜感激。

小智 4

当我研究构建一个表中包含数十亿行的分析解决方案时,我发现这种分析非常有用。

http://leiliweb.wordpress.com/2012/12/11/partitioned-table-and-index-strategies-using-sql-server-2008/