【问题标题】:What is the best way to store historical data in SQL Server 2005/2008?在 SQL Server 2005/2008 中存储历史数据的最佳方式是什么?
【发布时间】:2010-09-22 16:48:15
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 选择你的两个选项,让他们回答,这样我们就可以投票了

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


【解决方案1】:

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

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

【讨论】:

  • 您对获取城镇列表及其当前温度的最有效查询有什么看法。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

      • 我会将您的陈述稍微修改为“仅凭理论单独解决性能问题很少。”了解理论是在优化时有良好预感的唯一方法 - 否则您只是在胡思乱想并且可能永远不会提高性能。我猜这就是你的意思。 :)
      • 正确的索引应该消除对查询提示的任何需求。查询提示往往会妨碍优化器。在 12 年的 SQL Server 开发和设计中,我认为我不得不使用一次查询提示——也许两次。问题是,如果你的数据发生变化,一旦你有了查询提示,SQL Server 就无法适应。
      • 我同意伊恩和汤姆的观点。您需要了解理论,但优化始终是最终的。至于查询提示,我同意它们不应该是必要的,但是如果您使用内置优化器遇到死胡同(2005 有时会失败,而 2000 有时会成功),那么您可以使用提示。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

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

        您的数据似乎没有这个(城镇和日期是您唯一的明确维度),但是,在大多数数据仓库中,维度可能会像雪花一样或可能存在冗余,因此关于事实的其他维度存储在加载时间而不是雪花以提高效率 - 例如 State、Zip Code、WasItRaining、IsStationUrban(人为)。

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

        【讨论】:

          【解决方案7】:

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

          例子:

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

          record_id-----GUID

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

          【讨论】:

            【解决方案8】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-06-16
              • 2020-04-24
              • 2010-09-05
              • 2010-09-17
              • 1970-01-01
              • 2011-06-16
              • 1970-01-01
              相关资源
              最近更新 更多