特别是我正在处理类型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中的函数。在数据仓库上下文中应用它我会看到半开区间约定的优点如下:
因此,我倾向于采用半开区间法。然而,如果有一些广泛采用的使用闭区间方法的行业惯例,那么我可能会倾向于使用它,特别是如果它是基于实现这些系统的实际经验而不是我的抽象理论。
提前感谢任何见解或评论。
答案 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
。
通常,使用以下一个或多个字段:
取决于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倍。