22

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

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

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

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

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

4

8 回答 8

13

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

于 2008-11-17T16:23:54.390 回答
5

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

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

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

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

于 2008-11-17T16:30:11.507 回答
3

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

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

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

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

于 2008-11-17T16:37:54.223 回答
1

我建议保留在同一张表中,因为历史数据被经常查询。除非您将向表中添加更多列。

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

于 2008-11-17T16:20:29.563 回答
1

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

于 2008-11-17T16:26:37.350 回答
0

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

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

于 2008-11-17T16:37:27.717 回答
0

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

例子:

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

record_id-------GUID

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

于 2016-04-27T08:11:56.473 回答
0

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

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

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

于 2020-04-03T14:05:59.890 回答