處理事實表中的不同類型
我第一次使用維度建模,試圖建構一個從 OLTP 數據庫中提取數據的數據倉庫,但在弄清楚如何處理這種場景時遇到了一些麻煩。該數據庫跟踪捐贈到基金會。我想要一個事實表,這樣“糧食”是一次捐贈,即在“交易”級別。捐贈可以來自不同類型的捐贈者。例如,他們來自個人和公司,儘管在實踐中實際上有四個相關類別。源數據有每個捐助者類型的表格——所以有一個
individuals
表格和一個companies
桌子。個人和公司有非常不同的屬性,一個典型的報告要求是查看所有類型的捐贈總額,然後按捐贈者類型對捐贈進行更深入的研究。我的第一個想法是建立一個這樣的模式(順便說一句,顏色沒有意義,我只是在選擇突出顯示的表格時截取了螢幕截圖)
由於公司和個人具有如此不同的屬性,因此我們的想法是將它們保存在自己的表格中並讓它們成為維度。(請記住,在實際案例中實際上有 4 種以上的類型)。
但這顯然不是一個好方法,因為這意味著事實表中會有很多 NULL 外鍵。我讀過這是一個禁忌(儘管我不確定為什麼)。
另一種選擇是將 Companies 和 Users 表合併到一個大的 Donors 表中,如下所示
這以維度表的簡單性為代價從事實表中消除了 NULL 外鍵。Donor 維度表現在非常寬,並且包含許多空屬性(再次記住,將表示 4 種以上的捐助者類型,每種類型都有自己獨特的屬性)。
最後,可以選擇使用引用 Company 和 Individual 表的 Donor 維度。這可能是這樣的:
現在所有空外鍵都在施主維度表中。然而,顯然,這不再是星型模式。
我一直在尋找我能想到的任何地方來找到一些處理這種情況的一般原則,但我做不到。我只是想知道是否有一種標準的方法來處理這個問題,因為它似乎應該是數據倉庫中的一個標準問題。
我會避開第 3 個選項。它被稱為雪花而不是星形模式。這是一個相當先進的解決方案,可以在必要時使用,但有其自身的缺點。在尋找數據倉庫設計技巧時,像往常一樣參考 Kimball。
這就是他們在《雪花、支腿和橋樑》中所說的:
我們通常鼓勵您在單個維度表中處理多對一的層次關係,而不是雪花。對於有經驗的 OLTP 數據建模者來說,雪花可能看起來是最佳的,但對於 DW/BI 查詢性能來說,它們並不是最佳的。連結的雪花表給直接暴露於表結構的使用者帶來了複雜性和混亂;即使使用者從表中緩衝,雪花也會增加複雜性
當談到 1 或 2 時,我會說這取決於報告要求以及維度成員(維度中的記錄)應如何被視為要報告的一個“軸”。在一個維度中組合多種類型的記錄可能會帶來好處(例如定義層次結構和屬性關係以提高性能),但在這種情況下,我傾向於為不同的實體使用單獨的維度。同樣,Kimball 在維度建模
的基礎知識中解釋了這一點,但他們有更多關於該主題的文章。
規則 #1:將詳細的原子數據載入到維度結構中。
規則 #2:圍繞業務流程建構維度模型。
規則 #8:確保維度表使用代理鍵。
當涉及到事實表外鍵中的 NULL 值時,
surrogate keys
應該使用無論如何都應該使用的方法來解決這些問題。我在這裡回答了一個相關問題,但它基本上再次歸結為為 Nulls 選擇預設值,它解釋了您應該如何處理維度中的缺失數據。
應該避免空值的第一個場景是當我們在 ETL 過程中遇到一個空值作為事實表行的外鍵時。在這種情況下我們必須做點什麼,因為事實表的外鍵欄位中的實際空值將違反參照完整性;
在某種程度上,您可以將其解釋為“NULLS 是一個禁忌”,但它實際上意味著“在您的維度中插入一個虛擬記錄,例如 N/A,並在您的事實表外鍵欄位中使用該記錄的代理鍵”
@TomV 已經很好地回答了這個問題,基本上,如果您想將每個案例拆分為單獨的維度,您可以使用代理鍵創建一個虛擬記錄。不能說它是否適合您的業務案例,但它很常見。
為了完整起見,這裡是 Kimball 關於 NULL 在 Fact 表中的詞:
空值測量在事實表中表現得很好。聚合函式(SUM、COUNT、MIN、MAX 和 AVG)都用空值做“正確的事”。但是,必須避免在事實表的外鍵中出現空值,因為這些空值會自動導致違反參照完整性。關聯的維度表必須具有表示未知或不適用條件的預設行(和代理鍵),而不是空外鍵。