在数据仓库中表示时间间隔的最佳做法是什么?

时间:2010-11-24 08:57:42

标签: database database-design data-warehouse

特别是我正在处理类型2 Slowly Changing Dimension并且需要表示特定记录处于活动状态的时间间隔,即对于每个记录我有 StartDate 结束日期。我的问题在于是否使用已关闭 [StartDate,EndDate] )或半开 [StartDate,EndDate] < / em>)表示此的间隔,即是否包括间隔中的最后日期。举一个具体的例子,说记录1从第1天到第5天是活跃的,从第6天开始记录2变得活跃。我是否将记录1的EndDate设为等于5或6?

最近我开始思考半开放区间最好基于Dijkstra:Why numbering should start at zero以及阵列切片和范围() Python中的函数。在数据仓库上下文中应用它我会看到半开区间约定的优点如下:

  • EndDate-StartDate 给出记录处于活动状态的时间
  • 验证:下一条记录的 StartDate 将等于上一条易于验证的记录的 EndDate
  • 未来校对:如果我后来决定将我的粒度从每日更改为更短的时间,那么切换日期仍然保持精确。如果我使用一个封闭的间隔并将EndDate存储在午夜的时间戳中,那么我将不得不调整这些记录以适应这种情况。

因此,我倾向于采用半开区间法。然而,如果有一些广泛采用的使用闭区间方法的行业惯例,那么我可能会倾向于使用它,特别是如果它是基于实现这些系统的实际经验而不是我的抽象理论。

提前感谢任何见解或评论。

3 个答案:

答案 0 :(得分:10)

我看过使用过的封闭版和半开放版。出于你所说的理由,我更喜欢半开放。

在我看来,半开放版本使预期的行为更清晰,更“安全”。谓词(a&lt; = x&lt; b)清楚地表明b意图在该区间之外。相反,如果您使用闭合间隔并在SQL中指定(x BETWEEN a AND b),那么如果某人不明智地使用一行的结尾作为下一行的开头,则会得到错误的答案。

将最新结束日期默认为DBMS支持的最大日期,而不是null。

答案 1 :(得分:6)

答案 2 :(得分:0)

嗯,标准的sql where my_field between date1 and date2是包容性的,所以我更喜欢包容性形式 - 而不是另一个是错误的。

对于通常的DW查询,这些(rowValidFrom, rowValidTo)字段通常根本不使用,因为事实表中的外键已经指向维度表中的相应行。

这些在加载过程中最需要(我们在这里讨论类型2 SCD),以查找匹配的业务键的最新主键。那时你有类似的东西:

select ProductKey
from dimProduct
where ProductName = 'unique_name_of_some_product'
  and rowValidTo > current_date ;

或者,如果您希望在加载前创建密钥管道:

insert into keys_dimProduct (ProductName, ProductKey)  -- here ProductName is PK
select ProductName, ProductKey 
from dimProduct
where rowValidTo > current_date ;

这有助于加载,因为在加载之前很容易将密钥表缓存到内存中。例如,如果ProductName是varchar(40)而ProductKey是整数,则密钥表每1000万行少于0.5 GB,便于高速缓存以进行查找。

其他常见变体包括were rowIsCurrent = 'yes'where rowValidTo is null

通常,使用以下一个或多个字段:

  • rowValidFrom
  • rowValidTo
  • rowIsCurrent
  • rowVersion

取决于DW设计师和有时使用的ETL工具,因为大多数工具都有SCD类型2加载块。

似乎对使用额外字段所使用的空间感到担忧 - 因此,我将在此估计在维度表中使用一些额外空间的成本,如果没有其他原因那么方便。

假设我使用了所有row_字段。

rowValidFrom date       = 3 bytes
rowValidTo   date       = 3 bytes
rowIsCurrent varchar(3) = 5 bytes
rowVersion   integer    = 4 bytes

这总计15个字节。有人可能会说这太多了9个甚至12个字节 - 好的。

对于1000万行,这相当于150,000,000字节~0.14GB

我查看了戴尔网站的价格。

Memory ~ $38/GB
Disk   ~ $80/TB = 0.078 $/GB 

我将假设raid 5(三个驱动器),因此磁盘价格将为0.078 $ / GB * 3 = 0.23 $ / GB

因此,对于1000万行,将这4个字段存储在磁盘成本0.23 $/GB * 0.14 GB = 0.032 $上。如果要将整个维度表缓存到内存中,则这些字段的价格将为每1000万行38 $/GB * 0.14GB = 5.32 $。相比之下,我当地酒吧的啤酒价格约为7美元。

今年是2010年,我确实希望我的下一台笔记本电脑拥有16GB内存。事物和(最佳)实践随着时间而变化。

修改

在过去15年中,有人搜索过,平均电脑的磁盘容量增加了大约1000倍,内存大约增加了250倍。