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

时间:2008-11-17 16:16:42

标签: sql sql-server performance tsql sql-server-2008

我的简化和做作的例子如下: -

让我们说,我想每天测量和存储所有世界城镇的温度(和其他值)。我正在寻找一种存储数据的最佳方式,以便在所有城镇中获得当前温度同样容易,因为它可以在一个城镇中获得历史上的所有温度。

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

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

选项1 - 相同的表存储当前和历史记录

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

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条记录),并且数据是最新的一天。当前数据与历史数据一样可能被查询。

8 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:5)

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

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

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

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

答案 2 :(得分:3)

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

在更大的场景中,我会定期将数据传输到数据仓库(使用Kimball样式的维度模型建模)并简单地清除实时数据 - 在像您这样的简单场景中,可能会有效地< strong> NO 实时数据 - 这一切都直接进入仓库。当以不同方式切割数据并存储具有各种维度的大量事实时,维度模型具有许多优点。即使在数据仓库场景中,通常也会按日期对事实表进行分区。

您的数据可能看起来不是这样(Town和Date是您唯一明确的维度),但是,在大多数数据仓库中,维度可以雪花结构或者可以存在冗余,因此存储的事实还有其他维度加载时间而非雪花以提高效率 - 如州,邮政编码,WasItRaining,IsStationUrban(人为)。

这可能看起来很愚蠢,但是当你开始挖掘数据仓库中的结果数据时,这会让人问这样的问题 - 在城市环境中下雨的那天,缅因州的平均温度是多少? - 如果没有加入一大堆表,那就更容易理解了(即它不需要你的规范化模型上的大量专业知识,并且执行速度非常快)。有点像棒球中无用的统计数据 - 但有些显然是有用的。

答案 3 :(得分:1)

我建议保留在同一个表格中,因为历史数据的查询频率相同。除非你要在表格中添加更多列。

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

答案 4 :(得分:1)

另一种选择可以是为一个表获取所有数据,并查看当前温度。这不会有助于提高性能,但可能有助于提高可读性/可维护性。如果你有适当的sql版本,你甚至可以使用索引视图来提高性能。

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

如果将所有内容存储在一个表中,您将如何创建关系数据库。

示例:

ID -------------- GUID ---- PK

RECORD_ID ------- GUID

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

答案 7 :(得分:0)

您可能要考虑使用Time series database,而不是为此尝试优化关系数据库。这些已经针对基于时间的数据进行了优化。 它们的一些优点是:

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

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

相关问题