繁体   English   中英

在 SQL Server 2005/2008 中存储历史数据的最佳方式是什么?

[英]What is the best way to store historical data in SQL Server 2005/2008?

我的简化和人为的例子如下:-

假设我想每天测量和存储世界上所有城镇的温度(和其他值)。 我正在寻找一种存储数据的最佳方式,以便获取所有城镇的当前温度就像获取一个城镇的所有历史温度一样容易。

这是一个很容易解决的问题,但我正在寻找最佳解决方案。

我能想到的两个主要选项如下:-

选项 1 - 同一个表存储当前和历史记录

将所有当前和存档记录存储在同一个表中。

IE

CREATE TABLE [dbo].[WeatherMeasurement](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

这将使一切变得简单,但是获取城镇列表和当前温度的最有效查询是什么? 一旦表中有数百万行,这会扩展吗? 在表中添加某种 IsCurrent 标志有什么好处吗?

选项 2 - 将所有存档记录存储在单独的表中

将有一个表来存储当前的实时测量值

CREATE TABLE [dbo].[WeatherMeasurement](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

以及存储历史存档日期的表(可能由触发器插入)

CREATE TABLE [dbo].[WeatherMeasurementHistory](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

这具有保持主要当前数据精简且查询非常高效的优点,但代价是使模式更复杂和插入数据更昂贵。

哪个是最好的选择? 有没有我没有提到的更好的选择?

注意:我简化了架构以帮助更好地关注我的问题,但假设每天都会插入大量数据(100,000 条记录),并且数据是一天的最新数据。 当前数据与历史数据一样有可能被查询。

它取决于应用程序的使用模式......如果使用模式表明历史数据将比当前值更频繁地查询,那么将它们全部放在一个表中......但是如果历史查询是例外,(或少于10% 的查询),并且更常见的当前值查询的性能将受到将所有数据放在一个表中的影响,那么将这些数据分离到它自己的表中是有意义的......

我会将数据保存在一张表中,除非您对当前数据(使用中)或历史数据(数量)有非常严重的偏见。 在大多数情况下,带有 DATE + TOWNID(按此顺序)的复合索引将消除性能问题(尽管显然我们目前没有数据来确定这一点)。

我想知道的一件事是是否有人想要来自城镇的当前和历史数据的数据。 如果是这样,您至少创建了一个新视图来担心该方向可能出现的性能问题。

不幸的是,这是您可能需要根据现实世界数据分析您的解决方案的事情之一。 我个人在很多情况下都使用了上面指定的复合索引,但也有一些边缘情况我选择将历史记录分解到另一个表中。 嗯,实际上是另一个数据文件,因为问题是历史记录密集了,我单独为它创建了一个新的数据文件,以避免使整个主数据文件集膨胀。 性能问题很少通过理论来解决。

我建议阅读索引使用的查询提示,并“覆盖索引”以获取有关性能问题的更多信息。

您的表非常狭窄,可能会在单个正确索引的表中执行,该表永远不会超过 SQL Server 在传统规范化 OLTP 模型中的容量,即使对于数百万行也是如此。 即使使用双表模型,也可以通过在 SQL Server 中使用表分区来减轻优势。 所以与单表模型相比,它没有太多值得推荐的地方。 这将是 Inmon 风格或“企业数据仓库”场景。

在更大的场景中,我会定期将数据传输到数据仓库(使用 Kimball 风格的维度模型建模)并简单地清除实时数据 - 在像您这样的一些简单场景中,可能实际上没有实时数据 -这一切都直接进入仓库。 维度模型在以不同方式对数据进行切片并存储具有各种维度的大量事实时具有很多优势。 即使在数据仓库场景中,事实表也经常按日期分区。

您的数据似乎没有这个(城镇和日期是您唯一的显式维度),但是,在大多数数据仓库中,维度可能会雪花状或可能存在冗余,因此在加载时存储的事实会有其他维度而不是使用雪花来提高效率——比如 State、Zip Code、WasItRaining、IsStationUrban(人为设计的)。

这可能看起来很愚蠢,但是当您开始在数据仓库中挖掘数据以获取结果时,就会提出以下问题:在城市环境下雨的一天,缅因州的平均温度是多少? - 只是在不加入一大堆表格的情况下更容易上手(即它不需要很多关于规范化模型的专业知识并且执行速度非常快)。 有点像棒球中无用的统计数据 - 但有些显然是有用的。

我建议保留在同一张表中,因为查询历史数据的频率一样高。 除非您将向表中添加更多列。

当大小成为问题时,您可以按十年将其分区,并使用存储过程联合请求的行。

另一种选择可能是为所有数据查找一个表并查看当前温度。 这对性能没有帮助,但可以很好地提高可读性/可维护性。 如果您有合适的 sql 版本,您甚至可以使用索引视图来提高性能。

我将使用带有索引视图的单个表来为我提供最新信息。 SQL 2005 和 2008 服务器是为数据仓库设计的,因此在这种情况下应该能很好地执行。

如果您有一个需要经常写入数据库的数据模式,那么最好的选择是拥有一个活动表和存档表,您可以在某个时间间隔批量更新。

如果您将所有内容存储在一张表中,您将如何制作关系数据库。

例子:

id--------------GUID----PK

record_id-------GUID

每次插入新记录时,[id] 都会改变,但 [record_id] 将保持不变。 现在,如果您必须将它与地址表链接起来,您将如何做到这一点?

与其尝试为此优化关系数据库,不如考虑使用时间序列数据库 这些已经针对处理基于时间的数据进行了优化。 它们的一些优点是:

  • 查询基于时间的键更快
  • 大数据吞吐量
    • 由于默认操作只是一个附加操作,因此可以很快完成。 InfluxDb支持数以百万计的数据点每秒)。
  • 能够更积极地压缩数据
  • 对时间序列数据更加用户友好。
    • API 倾向于反映时间序列数据的典型用例
    • 可以自动计算聚合指标(例如窗口平均值)
    • 通常可以使用特定的可视化工具。

我个人喜欢使用开源数据库InfluxDB ,但也有其他不错的选择。

暂无
暂无

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

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