Data-Warehouse

在星型模式中,當維度具有日期屬性時我應該怎麼做?

  • March 3, 2017

我正在嘗試了解維度模型和星型模式。假設我有一個銷售事實表,記錄零售店的總銷售額,例如,有四個維度:日期、客戶、商店和促銷(如在促銷活動中,如優惠券)。(下面的偽模式)。

我真的很喜歡用星期幾等屬性預先填充 Date 維度的想法,這樣您就可以通過看似複雜的條件(如“過去 10 年第二季度的星期六”)輕鬆過濾事實。

現在,假設我希望 Promotion 維度具有 Start_Date 和 End_Date 屬性,它們表示促銷的開始和結束。我該怎麼做呢?我想了想,可以想出三個不太理想的解決方案:

  1. 使 Start_Date 和 End_Date 成為正常的原子屬性(ISO8601 字元串或數據庫的日期時間對象),並且只允許有限的過濾。

  2. 為 Date 表創建 Start_Date 和 End_Date 外鍵,打破星型模式,但允許與完整 Date 維度相同的過濾功能。

  3. 包括諸如 Start_Date_Day_of_Week、Start_Date_Quarter 之類的屬性,保持星型模式但增加了維度大小,並且實質上複製了促銷維度中的日期維度的結構。

Sales Table
-----------
Date key      (FK to Dates table)
Promotion key (FK to Promotions)
Customer key  (FK to Customers table)
Store key     (FK to Stores)
Sales Amount  

Date Table
----------
Date Key (PK)
Month
Day of week
Day of month
Day of Quarter
Day of year
Holiday?
Quarter
Day since Epoch
Month since Epoch
etc...

Promotion Table
---------------
Promotion Key (PK)
Type (Coupon code, 2-for-1 sale, 50% off, etc)
Start_Date
End_Date

Customer Table
--------------
Customer Key (PK)
Name 
Age
Sex
etc...

Stores Table
------------
Store Key (PK)
Address
City State
Zip
etc...

老問題,我知道原來的海報是無效的,但因為它出現在Google搜尋中,我想我會添加我的想法。

  1. 使 Start_Date 和 End_Date 成為正常的原子屬性(ISO8601 字元串或數據庫的日期時間對象),並且只允許有限的過濾。

如果主要目標是提供資訊(即人們希望在報告中包含促銷的開始/結束日期),則將日期屬性放入現有維度是有意義的。但是,如果打算進行過濾,那麼在原子日期屬性上進行過濾會比較痛苦。

  1. 為 Date 表創建 Start_Date 和 End_Date 外鍵,打破星型模式,但允許與完整 Date 維度相同的過濾功能。

這種類型的雪花被稱為 Outrigger Dimension 並且在星型模式中是可以接受的。(http://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/Dimension-modeling-techniques/outrigger-dimension/)。我想這就是你所做的。

  1. 包括諸如 Start_Date_Day_of_Week、Start_Date_Quarter 之類的屬性,保持星型模式但增加了維度大小,並且實質上複製了促銷維度中的日期維度的結構。

重複會變得混亂(維護多個日期欄位,特別是因為您在同一維度中有多個日期)。它還使未來的維護更加複雜:如果你想改變你的日期維度,你必須在幾十個地方重複這個改變(或者有不一致的使用者體驗)。

另一方面,這可能是一個有效的選項,例如,如果您知道人們想要過濾促銷活動的方式只有一兩種。例如,如果您知道最終使用者想要快速過濾到有效促銷或“過去 30 天內關閉的促銷”,您可以計算並將其添加為促銷維度中的特定屬性,而不是連結到完整日期維度促銷開始和結束日期。(雖然一開始只是一兩個屬性可以迅速擴展,因為最終使用者會發現他們想要過濾的時間段越來越多。)


有第 4 和第 5 個選項,具體取決於您打算按促銷開始/結束日期過濾的具體內容:

4) 在銷售表中添加促銷開始/結束日期欄位作為鍵。

每次使用促銷時,您都將儲存相同的資訊,因此乍一看,感覺就像很多重複。但非規範化是星型模式中的遊戲名稱。如果您的目標是根據促銷開始或結束日期(即促銷開始日期為上個月的銷售)篩選銷售,我會建議在外支架維度上這樣做。

5) 為促銷創建一個新的、無事實的事實表

如果您的目標根本不是過濾銷售,那麼無事實事實表可能是更好的解決方案。例如,這可以告訴您在給定日期有多少促銷活動有效(無論是否有相關銷售)。更多資訊:http ://www.kimballgroup.com/2011/04/design-tip-133-factless-fact-tables-for-simplification/


我在維度建模方面的經驗是,最好的解決方案通常取決於最終使用者想要完成的任務。如果您(或他們)還不確定他們想要完成什麼(即您知道促銷活動有開始和結束日期,僅此而已),我將從選項#1 開始。這無需太多工作就可以將資訊放入您的模型中。

如果後來發現最終使用者正在嘗試按開始和結束日期過濾銷售,那麼我會考慮 #2 或 #4。如果最終使用者正在嘗試獨立於銷售來分析促銷,我會看#5。

我建議使用選項#2。日期是星型模式世界中的一個特例:加入該維度所獲得的好處遠遠超過了你想要這樣做的雪花。

選項 #1 意味著您將失去從一開始就擁有數據倉庫的許多分析優勢:例如,您不能輕易地做一些事情,比如根據年齡來尋找客戶在模式上的差異。

選項#3 將涉及維度表的巨大爆炸:您將無緣無故地攜帶許多額外的屬性。通常這還不錯——星型模式的全部意義在於非規範化和簡化你的維度結構——但這只是一種罕見的情況,你會經常為這麼多屬性這樣做,並且每次更新維度中的一行時,您可能還必須更新所有這些屬性。這會對您的增量維度負載產生負面的性能影響,而不會真正使業務使用者更容易理解模型。這甚至可能使事情變得更糟:如果您在維度上的每個日期都有 70 多個與日期相關的屬性(想想標準年份、不同類型的會計年度等),他們可能會目瞪口呆。它'

為了幫助您晚上睡覺,您還可以創建兩個圖形模型:一個是真實數據模型,另一個是“無日期”數據模型。“無數據”模型將剝離其他維度和日期之間的聯繫,看起來更像是一個自然的星型模式。

引用自:https://dba.stackexchange.com/questions/28775