假设我的公司销售许多产品,例如域名,T恤和面包车。
在我当前的数据仓库星型模式设计中,我有一个发票项目的事实表,其中包含以下(略微简化的)模式
fact_invoice_item
id | pk
invoice_item_id | id of invoice in OLTP
dim_customer_key | fk to customer dimension
dim_product_key | fk to product dimension
dim_billing_date_key | fk to date dimension
dim_due_date_key | fk to date dimension
invoice_amount | fact
item_amount | fact
dd_invoice_id | degenerate dimension to group together invoice items on the same invoice
我现在想开始围绕这些发票项目记录元数据。例如,如果购买了域名,那么域名是什么。如果买了一辆面包车,车牌号是多少。如果买了T恤,颜色是什么。在(理想情况下)遵守星/星座模式的同时实现这一目标的最佳方法是什么?
目前的想法:
选项1
从invoice_item_metadata
表中有一个带有fk的通用invoice_item
维度表。此维度表可以以json形式存储项元数据。或者甚至只是以json形式将购买元数据存储在事实表中。这会让事情变得有点棘手,因为我需要解压缩json以对其进行任何分析。
选项2
为每种购买的产品提供事实表,例如。 fact_domain_purchase
和fact_van_purchase
。这些事实表可以有自己的结构,以最好地适应产品元数据。这似乎是合乎逻辑的,但后来我开始认为一个域更像是一个SCD,因为它可能具有暂停/活动/过期等属性,这些属性可能会随着时间的推移而发生变化。这让我认为我可以在fact_domain_purchase
表中使用带有fk的dim_domain
表,但是dim_domain
表将以与fact_domain_purchase
表相同的速率增长,这是不希望的。
有没有人对如何处理这种情况有任何好主意?我确信我不能成为第一个解决这个问题的人,但我发现从谷歌那里获得任何有用的东西都很困难。在此先感谢您的帮助
物品属性在产品维度中理想地描述,即每个T恤尺寸和颜色都有额外的product_id。
如果处理更多唯一项(产品维度中未完全覆盖属性),则在事实表中添加缺少的属性。
在主要的一个事实表中,这意味着它包含所有产品子类型(T恤,面包车......)的属性,但只有那些用于selled子类型的属性被填充所有其他都是NULL。
或者(如果您的格局是高度异构的),您可以为每个子类型定义一个单独的事实表,该事实表与主事实表相关,并具有可选的1:1关系。这里没有一般规则是有效的,唯一的可能性是对解决方案进行原型设计,看看哪些有效,哪些失败。
我明确不建议使用代理键(例如dim_billing_date_key)作为时间维度而不是本机DATE列(引用时间维度)。事实表通常基于时间维度进行分区,并且代理键可能会干扰分区修剪,这是查询性能的关键 - 在原型中也要仔细测试。
我认为你需要解决两件事,where
和how
来存储你的元数据
对于存储,您的用例是Extension table
的完美示例
fact_invoice_item_ext
id | pk
fact_invoice_item_id | id of fact_invoice_item table
此表类似于您的事实表,但它基本上是您的事实记录的扩展,用于存储其他(也可能是可选的)数据
至于如何,因为您不知道数据的特征,您可以在表中创建键值对来存储信息。它比json更容易访问并且更易于管理,因此这些附加列将存储键值对
attr_key | attribute key; domain, van, t-shirt etc.
attr_value | attribute value; domain name, license plate etc.
使用此方法,您可以为发票项目提供多个附加属性(元数据)。
如果这有意义,请告诉我,或者您对此概念有其他疑问