归一化时间序列数据

时间:2013-02-19 09:46:40

标签: relational-database normalization time-series snowflake-schema 6nf

我正在创建一个存储大量事件的数据库。会有很多这些,并且每个都有一个精确到第二个的相关时间。举个例子,像这样:

Event
-----
Timestamp
ActionType (FK)
Source (FK)
Target (FK)

行动,来源和目标均为6NF。我想保持Event表的规范化,但我能想到的所有方法都存在问题。为了清楚我对数据的期望,绝大多数(99.9%)的事件只有上述四个字段才是唯一的(因此我可以将整行用作PK),但少数例外情况不容忽视

  1. 使用代理键:如果我使用四字节整数,这是可能的,但似乎只是无缘无故地膨胀表。此外,我担心长时间使用数据库并耗尽密钥空间。

  2. 向事件添加计数列:由于我希望小计数我可以使用较小的数据类型,这对数据库大小的影响较小,但它需要upserts或pooling插入前数据库外的数据。其中任何一个都会增加复杂性并影响我对数据库软件的选择(我当时正考虑使用Postgres,它会进行upserts,但不乐意。)

  3. 将事件分成小组:例如,同一秒内的所有事件都可以是Bundle的一部分,该Event可以拥有该组的代理键,另一个用于里面的每个事件。这为数据库增加了另一层抽象和大小。如果不是重复的事件变得普遍,那将是一个好主意,但在其他方面似乎有点矫枉过正。

  4. 虽然所有这些都是可行的,但他们感觉不适合我的数据。我在考虑只是做一个典型的Snowflake并且没有在主{{1}}表上强制执行唯一性约束,但在阅读了像this one之类的PerformanceDBA答案后,我想也许有更好的方法。

    那么,将少量重复事件的时间序列数据保持正常化的正确方法是什么?

    编辑澄清 - 数据的来源是日志,主要是平面文件,但有些是在各种数据库中。该数据库的一个目标是统一它们。没有一个来源的时间分辨率比第二个更精确。这些数据将用于诸如“有多少不同来源对目标超过间隔执行操作?”之类的问题。 Interval不会少于一个小时。

1 个答案:

答案 0 :(得分:3)

最简单的答案似乎是

  • 以更高的精度存储时间戳,或
  • 将时间戳存储到第二个并重试(稍后时间戳),如果INSERT由于重复键而失败。

您提到的三个想法中没有一个与规范化有关。这些是关于存储什么的决定;在概念层面,您在决定要存储的内容后规范化。行意味着什么(因此,每列意味着什么)是重要的;这些含义构成了表格的谓词。谓词允许您从较旧的真实事实中获得新的真实事实。

使用整数作为代理键,您不可能耗尽密钥空间。但是你仍然必须声明自然键,所以在这种情况下代理不会对你有用。

添加“count”colummn 是有意义的,如果计算事物是有意义的;否则它没有。看看这两个例子。

Timestamp            ActionType  Source  Target
--
2013-02-02 08:00:01  Wibble      SysA    SysB
2013-02-02 08:00:02  Wibble      SysA    SysB

Timestamp            ActionType  Source  Target  Count
--
2013-02-02 08:00:01  Wibble      SysA    SysB    2

在意义中的区别是什么? “时间戳”的含义尤为重要。规范化基于语义;您需要做什么取决于数据的含义,而不是列的名称。

将事件分成小组可能有意义(如添加“计数”列可能有意义),如果事件组在您的系统中有意义。