我们有一个包含四个维度表和一个事实表的数据仓库设计:
- dimUser id, email, firstName, lastName
- dimAddress id,城市
- dimLanguage id, language
- dimDate id, startDate, endDate
- factStatistic id, dimUserId, dimAddressId, dimLanguageId, dimDate, loginCount, pageCalledCount
我们的问题是:我们想要构建事实表,其中包括计算统计数据(取决于userId,日期范围)和填充外键。
但是我们不知道怎么做,因为我们不知道如何使用自然键(根据我们阅读的文献,这似乎是解决我们问题的方法)。
我认为一个自然的键是userId,它在所有计算维度数据的ETL作业中都需要。
但是有很多困难:
- 在ETL作业load()中,我们使用INSERT IGNORE INTO进行批量插入以删除重复项=>我们不知道生成的代理键
- 如果我们创建元数据(包括一组dimension_name, surrogate_key, natural_key),这将无法工作,因为重复消除
问题似乎是重复消除策略。有没有更好的方法?
如果您的事实表正在跟踪每个用户的登录和页面调用,那么您应该有一组跟踪这些事情的源表,您将从这些源表中加载事实表数据。我可能会按照每个用户/登录日期一行的粒度来构建事实表——如果可能的话,甚至更低来持久化原子数据。
在这里,您将拥有一个具有两个维度的事实表- User和Date。你也可以把地址和语言作为维度来保存,但它们实际上只是用户的属性。
您的维度应该有代理键,但也应该有可用的源"业务"或"自然"键——或者作为维度本身的属性,或者像您的同事建议的那样通过映射表。使用映射表并不是"错误的"——当有多个源时,它确实使事情变得更容易。
如果将业务键存储在映射表中,或者作为属性存储在维度中,那么对于要加载到事实中的每一行,只需对dim或映射表进行简单查找(通常通过连接),以获取用户的代理键(然后从用户获取用户的"当前"地址/语言,以保存在事实上)。日期维度通常有一个代理键,以YYYYMMDD或其他"自然"格式存储—您可以从源记录上的日期信息生成它,您正在加载到事实中。
不要强制单个查询,尝试在单独的查询中加载数据,并在某些提供程序中混合数据…