我目前的任务是为相对大量的数据实现存储模式。首先将访问数据以确定当前data point
值,但我还需要跟踪过去六个月的数据趋势/分析历史。
添加了最近的要求以跟踪过去一小时的min
/ max
/ sum
值。
注意:理想情况下,我想考虑使用MongoDB选项,但是我需要证明我已经首先用尽了SQL-Server选项。
数据
下表代表主要数据源(最常查询)。该表将有大约五百万行。在初始数据加载之后,数据更改将主要是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])
)
第二个表明显更大,大约为31亿行(代表过去六个月的数据)。六个月以上的数据将被清除;否则严格执行数据INSERT
声明(〜200行/秒,720,000行/小时,1,700万行/周)。
// 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])
)
可以预期的是,随着跟踪的数据点值的数量增加到400行/秒,此表的大小将增加一倍(因此达到约100亿个也不是不可能的)。
问题(是的,我要问的不止一个...它们密切相关)。
我当前正在使用SQL-Server 2008 R2 Standard Edition数据库。如果可以通过表分区获得所需的性能水平,或者如果使用SQL-Server无法达到所需的性能水平,则可能会升级到Enterprise Edition。我希望您在以下方面提供意见:
1)考虑到我需要计算min
,max
和sum
过去一小时(在now - 60 minutes
)。跟踪最新数据的最佳方法是什么:
将最近的数据保存在数据服务的内存中。用每个数据更新写出计算出的最小/最大/平均值。
在每个UPDATE语句期间,从历史记录表中查询最近的历史记录(是否影响下一个问题?)。查询将访问最新数据以获取数据点值,并且应该仅扫描最后一百万条记录左右?
将最近的历史记录存储在DataPointValue行本身中,以避免历史记录表查找?也许存储为分隔字符串并在UPDATE proc中处理?
我没有考虑过的其他选择?
2)对于DataPointValueHistory
,对datable的查询将始终是by dataPointId
和一个或多个valueId
。查询的数据通常是最后一天,一周或一个月,但在某些情况下可能是整个六个月。
我目前正在生成一个样本数据集,以尝试通过dataPointId / valueId / timeStamp或timeStamp / dataPointId / valueId进行聚类是否更有意义。如果有人在处理这种尺寸的桌子方面有经验并且愿意提供自己的见识,我们将不胜感激。我倾向于使用后一种选择以避免索引碎片,但是查询性能至关重要。
集群
DataPointValueHistory
由dataPointId - > VALUEID - >的timeStamp集群
DataPointValueHistory
通过时间戳- > dataPointId - > VALUEID
3)最后,如上所述,我认为将DataPointValueHistory
表分区是有意义的。任何有关如何最好地划分历史数据的建议将不胜感激。
如果首先按时间戳进行群集,我认为数据应该按周进行分区(总共27个分区)。第27周后将清除最旧的分区。
如果首先由dataPointId进行聚类,我想应该按ID的某个模数对数据进行分区?
由于我在表分区方面的经验非常有限,您的专业知识将不胜感激。