我正在创建一个存储大量事件的数据库。会有很多这些,并且每个都有一个精确到第二个的相关时间。举个例子,像这样:
Event
-----
Timestamp
ActionType (FK)
Source (FK)
Target (FK)
行动,来源和目标均为6NF。我想保持Event
表的规范化,但我能想到的所有方法都存在问题。为了清楚我对数据的期望,绝大多数(99.9%)的事件只有上述四个字段才是唯一的(因此我可以将整行用作PK),但少数例外情况不容忽视
使用代理键:如果我使用四字节整数,这是可能的,但似乎只是无缘无故地膨胀表。此外,我担心长时间使用数据库并耗尽密钥空间。
向事件添加计数列:由于我希望小计数我可以使用较小的数据类型,这对数据库大小的影响较小,但它需要upserts或pooling插入前数据库外的数据。其中任何一个都会增加复杂性并影响我对数据库软件的选择(我当时正考虑使用Postgres,它会进行upserts,但不乐意。)
将事件分成小组:例如,同一秒内的所有事件都可以是Bundle
的一部分,该Event
可以拥有该组的代理键,另一个用于里面的每个事件。这为数据库增加了另一层抽象和大小。如果不是重复的事件变得普遍,那将是一个好主意,但在其他方面似乎有点矫枉过正。
虽然所有这些都是可行的,但他们感觉不适合我的数据。我在考虑只是做一个典型的Snowflake并且没有在主{{1}}表上强制执行唯一性约束,但在阅读了像this one之类的PerformanceDBA答案后,我想也许有更好的方法。
那么,将少量重复事件的时间序列数据保持正常化的正确方法是什么?
编辑澄清 - 数据的来源是日志,主要是平面文件,但有些是在各种数据库中。该数据库的一个目标是统一它们。没有一个来源的时间分辨率比第二个更精确。这些数据将用于诸如“有多少不同来源对目标超过间隔执行操作?”之类的问题。 Interval不会少于一个小时。
答案 0 :(得分:3)
最简单的答案似乎是
您提到的三个想法中没有一个与规范化有关。这些是关于存储什么的决定;在概念层面,您在决定要存储的内容后规范化。行意味着什么(因此,每列意味着什么)是重要的;这些含义构成了表格的谓词。谓词允许您从较旧的真实事实中获得新的真实事实。
使用整数作为代理键,您不可能耗尽密钥空间。但是你仍然必须声明自然键,所以在这种情况下代理不会对你有用。
添加“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
在意义中的区别是什么? “时间戳”的含义尤为重要。规范化基于语义;您需要做什么取决于数据的含义,而不是列的名称。
将事件分成小组可能有意义(如添加“计数”列可能有意义),如果事件组在您的系统中有意义。