多个事实的事实表

5

我有一个维度(SiteItem),它有两个重要的属性:

perUserClicks 
perBrowserClicks

然而,在这个维度内,我有一些基于属性列的值组(我们称之为AboveFoldItems、LeftNavItems、OnTheFlyItems等),每个组都有更多特定于该组的事实:

AboveFoldItems: eyeTime, loadTime
LeftNavItems: mouseOverTime
OnTheFlyItems: doesn't have any extra, but may in the future

以下事实表模式是否正确?
DateKey   
SessionKey
SiteItemKey
perUserClicks 
perBrowserClicks
eyeTime
loadTime
mouseOverTime

看起来有点浪费,因为只有一些列与某些维度键相关(不相关的事实留空)。但是...这似乎是一个常见的问题,所以应该有一个通用的解决方案,对吧?

3个回答

4
我基本上同意Damir的回答,但由于你特定情况下的事实表非常窄,因此仍然有理由支持Aaron保留NULL值。
我们在特定主题领域中有几个星型模式,其中有多个事实表共享大多数(如果不是全部)维度(一致和内部)。有限范围的维度在整个企业中不被视为“一致”,但它们是我们所谓的“共享内部”维度。
现在,通常情况下,如果数据同时加载,使维度没有改变,您可以在键上连接两个事实表,但通常情况下,如果它们是传统缓慢变化的维度中的代理人,则不能在维度键上连接两个不同的星型模式。一般来说,您必须在维度内部而不是在代理人(除了通常的日期维度的特殊情况,它是不变的并且只有一个自然键)上使用自然键或“业务键”连接单独的星型。
请注意,当您连接这两个星型时,您必须使用LEFT JOIN,在这种情况下,您将产生NULL值,您仍然可能需要考虑这些值 - 因此,您实际上正在回到具有NULL值的原始模型! ;-)
额外事实表的好处更加明显,当您的表宽度较大,键集较小且数据的垂直分区产生空间节省以及更清晰的逻辑模型时 - 当键仅在一定程度上共享时尤其如此 - 有一个虚拟键或NULL键绝对不是一个好主意 - 这通常指向了一个维度建模问题。
然而,正如Aaron所说,如果你把它推向极端,你可以在每个事实表中有一个单独的事实列和共享键,这意味着键开销超过了事实成本,你真的会进入伪装的EAV模型。
我还会查看您是否处于Kimball的“维度太少”的情况。看起来您必须将良好的维度属性合并到SessionKey和SiteItemKey中 - 但是,如果没有看到您的整个模型和要求,很难说,但我认为您可能在低基数甚至雪花维度中具有一些用户人口统计信息,而无需完整的会话或站点维度。

谢谢讨论!我认为我有共享内部维度的情况。你将两个事实表连接的比较说明了为什么我们保留NULL而不是零(零会影响平均值,而我们选择具有NULL奇怪情况的)。我不能透露我们模式的更多信息,但你正确地指出,一些用户可以从额外的、更具体的维度中受益。 - Jeff Meatball Yang

3
实际上,没有一种优雅的解决方案,您可以使用可空列或使用EAV解决方案。我以前发布过有关EAV的帖子(并产生了很多评论,可能值得一读): 在某些情况下,我是这种模型的粉丝,但如果您的维度/属性不经常更改,则这可能只是徒劳无功的额外工作。只要周围的代码能够适当地处理它们,列中的NULL值确实不会浪费。

谢谢提供链接,并与EAV进行比较 - 我之前没有想到过这一点。 - Jeff Meatball Yang

1

你可以有多个事实表:factperUserClicks、factperBroWserClicks、factEyeTime等...

每个事实表都会有DateKey、SessionKey、SiteItemKey。这样,每个事实表中只会出现“有意义”的维度键。

理想情况下,在DW中不应该有NULL值——如果你将它们保留在同一个事实表中,使用零可能更合适。

就节省磁盘空间而言,我没有看到理想的解决方案——但是,在DW中,人们本来就应该为速度和(查询)简单性而牺牲空间。


问题在于我需要同时查询 SiteItem 的维度,并在一个用户定义的事实列表中检索聚合。看起来我可以将两个事实表连接起来,但需要进行 LEFT JOIN 才能正确聚合。 - Jeff Meatball Yang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接