引用: https://zhuanlan.zhihu.com/p/111979066
1 維度表的定義
在維度建模中,通常將指標的度量稱之為“事實”,將產生度量的環境稱之為“維度”。將描述同一個業務實體的的多個維度列組合在一起,就是常說的“維度表”。維度表是用戶分析數據的窗口,其提供了事件發生過程中的環境描述信息,能夠做數據查詢的過濾條件和數據分析的分組。維度設計既是維度建模的基礎,也是其關鍵所在,可以說,維度表設計的質量,將決定了整個維度模型分析能力的上限。
2 維度表的構成
維度表通常表示的是參與到業務過程中的一個業務實體(如,商品、賣家、買家、優惠券、時間等等),其每一行數據表示的是一個業務實體的實例(如,商品維度表中的一行表示的就是一個商品)。
2.1 維度表的結構
維度表一般由【代理鍵、自然鍵、維度屬性】三部分構成。如果有保留維度變化歷史或大型維度表的拆分需求,可能還會加入其它部分以做技術實現上的補充。
- 代理鍵:不具有任何業務含義,僅做維度表數據唯一性區分的屬性,通常以主鍵形式出現。
- 自然鍵:具有業務含義,是業務實體一個實例的唯一性區分(如,商品ID),在維度表中不一定做表的主鍵。
- 維度屬性:描述同一業務實體各種特征的維度列(如,商品維度表中的商品名稱、商品價格等)。
維度表中的代理鍵,會根據分析的需求決定是否存在,如果沒有需要保留追溯業務實體歷史變化的需求,一般情況會用自然鍵直接做為維度表的主鍵,這樣通常簡單、高校、且易於理解。代理鍵的存在主要是應對處理變化維度的需求。
2.2 維度表的內容
3 設計方法
維度表的設計就是確定維度屬性的過程,如何識別維度屬性、如何生成維度屬性,將是設計過程中需要着重考慮的地方。
3.1 維度表設計流程
3.1.1 選擇實體
維度表設計首先要選擇實體,也就是維度表所要描述的抽象對象。如,互聯網電商在交易過程中涉及到的實體有:買家、賣家、訂單、廣告等等,當然還有一些在不同業務場景下衍生出來的一些業務抽象實體,如優惠券、活動、商圈等都可以作為維度實體。 實體的選擇主要是結合業務流程,在需要建模的業務流程環節涉及到了哪些參與者,這些不同的參與者便是維度表描述的實體對象,維度表中的屬性,就是用來區分不同實體的特性。下面用電商平台的注冊環節舉例說明,電商網站的注冊,自然需要買家進行注冊賬號和個人信息,其中涉及買家(即消費者)實體。
3.1.2 確定主維表
確定主維表,主要是識別出維度表的主要數據來源。通常,業務系統中也會將相同類型業務實體進行統一存儲(即一張表),亦或是在大型企業有建設業務中台會提前做同類業務實體的數據融合(如,商品中心、用戶中心等)。但在沒有類似業務中台可以直接獲取全量維度實體數據的情況下,就需要自行確定業務實體數據的來源,並做融合。一般情況會將常規主要業務流程中產生的業務系統數據做為主維度表,因為其一般是維度表的主要數據來源,並且數據准確、豐富。例如,電商APP可能會有多個注冊入口,APP、微信、支付寶、分享外鏈等等,我們可能會將APP注冊流程中產生的數據表作為主維表,當然可能有的企業已經在用戶注冊系統已經將其他各種渠道注冊的用戶數據已經囊括進入。
3.1.3 確定輔維表
輔維表存在的目的有兩方面。一方面是補全主維表在維度實體的數據(如,用戶大部分是通過獨立注冊登錄APP,還有小部分是通過微信登錄、支付寶登錄等等);另一方面是為了尋找維度表所表示的業務實體的一些其他屬性描述輔助表(如,商品類目表、商品屬性表、用戶家庭關系表等),這些輔維表用來豐富維度表的屬性描述,增強維度表的表現性,同樣也能擴展維度表的分析能力。
3.1.4 識別維度屬性
維度表的維度屬性一般可以分為相對穩定的“固化屬性”和變動頻繁“動態屬性“。
“固化屬性”通常是和維度實體關系相對緊密且較為穩定的固有屬性,不依賴或很少依賴於其它的業務活動過程(如,商品維度表中的商品名稱、商品品牌等); ”動態屬性“通常是只能基於特定的事務過程或者活動關聯,在維度實體的層次上匯總得到的一些統計屬性(如,描述商品的近30天銷量,首次上架日期等)。
由於“固化屬性”和“動態屬性”的變更周期差異巨大,一般會在維度表的構建過程中結合具體的場景進行拆分,一方面是保證維度表能夠高效的產出,另一方面也是為追溯歷史數據提供合理的技術實現。
3.2 生成維度屬性
維度屬性的生成,既可能來自原始業務系統的即有的業務實體表(如,業務系統會有商品表/商品擴展表),同時也可能來自事務過程之后的數據統計(如,近商品近一天的銷量),無論維度屬性來自哪里,都可以參照以下建議不斷地豐富和完善維度屬性,維度屬性越是詳盡,維度模型/數據倉庫的分析寬度和深度才能更強大。
3.2.1 多增加文字描述
業務操作系統同步進入數倉的數據表中,通常會將某一屬性的可枚舉值一代碼的形式表示(如,商品類型<01:服裝;02:食物>),而代碼的具體含義會在表屬性的說明中或者在數據字典的說明文檔中。這樣做的目的是方便對其維護並提高在業務系統中的存取效率。 在數據倉庫這種分析型的系統中,為了能夠完善其可解釋性,最佳的方案是增加一個與代碼表示列對應的文字描述屬性列,目的是描述代碼表示列的具體含義,使分析人員可以更便捷的根據需要進行過濾、訪問和組織數據。
3.2.2 統一標志值
一些布爾類的屬性列,其屬性值在業務系統中可能會以各種不同的形式出現,如,可以是整形的0和1,或者是字符型的“Y”和“N”,亦或是“True”和“False”,統一張維度表中,不同的布爾類屬性列使用不同的表示方式,將會使維度表的使用效率大打折扣,分析人員在使用維度表的布爾類屬性列時需要不斷的去查詢說明文檔,確認每個屬性列的表示方式。 在生成維度屬性時,將這些布爾類的屬性列的標志值做統一規定,使用0/1或者Y/N進行表示,這樣其表示也更加明確,使用更加便捷,也不會在生成報表過程中其意義含糊不清。
3.2.3 屬性拆分
數據倉庫獲取的數據充滿了不確定性,既會有業務系統中表屬性的各種隨性組合,也會有一些標准化可按照特定規則拆分的屬性(如,客戶的身份證號碼、買家的收貨地址郵編等),如果能夠按照既定的規則對維度表的屬性做合理的拆分,將會進一步豐富維度表的表達能力。 業務系統中存儲的客戶身份號碼,可以依據身份號碼的構成規則進行拆分。18位身份證號碼,1-2位表示省、直轄市;3-4位表示地級市;5-6位表示區、縣;7-14位表示出生年月;第17位表示性別(男為單,女為雙)。這樣,依據身份證號碼的構成,一個身份證號碼,可以擴展出客戶戶籍省、市、區縣、出生年月、性別至少5個維度屬性,並且出生年月還可以進一步拆分擴展,每個拆分出的屬性,可參照上述1,增加對應的文字描述,完善代碼屬性值和文字描述屬性一一對應,拆分擴展后的維度表將會有更強的表達能力。
3.2.4 屬性組合
屬性組合與屬性拆分相互對應,屬性拆分的目的是從一個固定的編碼中獲取更加詳細的維度屬性,豐富維度的可解釋行;屬性組合則是相反的過程,是將一些具有相關性的維度屬性列進行組合,方便在查詢時的維度屬性使用或展示。 比如業務操作系統存儲的地區代碼或者地區名稱,我們會根據業務上的使用習慣會進行適當的組合,將省份、城市組合,或者將城市、區縣組合,在做查詢應用或頁面展示時都是不錯的選擇。通常會選擇根據業務需求進行適當組合,不必窮盡所有排列組合,因為數據倉庫建設的目的主要還是在於能更便捷的應用數據。
3.2.5 數值型維度屬性
考慮到“事實”通常是數值型,作為“維度”的數值型屬性往往容易被忽略掉。同時數值型屬性究竟是該被歸入“事實”中還是該被歸入到“維度”中也讓很多人感到困惑。簡單來講,數值型的屬性既可以作為“事實”,同時也可以作為“維度”屬性。 當數值型屬性用作聚合匯總時,那么無疑就是“事實”;用作查詢過濾條件或者分組鍵時,也可以作為“維度”屬性。比如“商品價格”,其可以同時出現在事實表和維度表中,在事實表中可以作為指標度量計算商品成交的平均價格,在維度表中則可以通過價格去分析商品在不同價格或者不同價格區間的成交情況。
3.2.6 統計型維度屬性
統計型維度屬性一般指並非維度實體固有的屬性,而是隨着業務的發展,在業務過程中產生的一些實體相關的行為統計信息(如,近30天商品銷量)。這些統計信息一般是作為分析的結果數據進行輸出,但由於其描述仍然是維度實體,自然也可以作為維度屬性來應用。統計型維度屬性需要考慮的問題主要在於更新的頻率,一般將其與維度的基本屬性進行拆分開來存儲,基本屬性相對變化較少,而統計型維度屬性易變的體質通常會作為維度基礎屬性表的擴展表進行存儲和應用。
3.2.7 通用型維度屬性
通用型維度屬性是在使用數倉過程中不斷總結,不斷沉淀的一些與業務強相關的維度屬性。一般是具有復雜計算邏輯的維度屬性,如需要經過多張表關聯計算,或者在企業范圍內超高頻使用的分析邏輯。不斷的沉淀這些通用的維度屬性,一方面是提高下游使用的便捷性,另一方面也能保證數據口徑的一致性。如,在業務上可能需要分析分銷OR自營商品數據表現,最佳實現是將商品“是否分銷”的維度屬性進行封裝,統一構造進入維度表中,保證數據口徑的一致性。
4 設計原則
數據倉庫模型在設計過程中需要一些設計原則來做一些規范約束,這樣才不會在建設過程中,發現越建設越雜亂,經常需要不斷返工,重新推倒以前的東西,再重新糾正,導致歷史包袱過重。
4.1 主鍵選擇
維度表主鍵通常會有自然鍵、代理鍵兩種選擇:
- 代理鍵:不具有任何業務含義,僅做維度表數據唯一性區分的屬性;
- 自然鍵:具有業務含義,是業務實體一個實例的唯一性區分(如,商品ID,一個商品ID就代表一個獨立商品)。
兩種主鍵選擇因業務而異,筆者從業依賴,所見最多的還是以“自然鍵”作為主鍵居多。一方面主要是“自然鍵”做主鍵易處理、好理解,和業務系統意義相同;另一方面大多業務場景很少有需要追溯歷史變化的需求。 在此做一些建議:
- 如業務上對該維度表表示的業務實體沒有或很少有追溯歷史變化的需求,可直接采用自然鍵作為主鍵使用(如,商品ID,用戶ID等),因為生成代理鍵的過程也會有耗費大量的數據加工性能,並且如何能保證代理鍵的唯一性,也需要去做設計方案。
- 如卻有業務場景肯能會需要追溯歷史變化,可根據需求,結合維度表拆分,將拆分后的維度表,一部分用“自然鍵”做主鍵,另一部分涉及到緩慢變化的維度屬性,通過“代理鍵”做主鍵,這樣可以綜合兩種主鍵的優勢,同時滿足業務需求。
4.2 一致性原則
維度表的一致性是關系到數據模型能否進行跨業務橫向鑽取做多業務流程分析的關鍵。一致性原則主要體現在三個方面:結構一致性、語意一致性、內容一致性。 結構一致性:同一實體的同一維度屬性在不同維度表/事實表中,需有相同的維度屬性列名、相同的數據類型定義,以保證內容的同一性。 語意一致性:不同維度表/事實表中,相同維度屬性所表達的業務含義需要是一致的,否則在使用過程中會出現相同指標、不同結果的數據指標不一致性。 內容一致性:是需要在同一實體同一維度屬性在不同維度表中需要有相同的數據內容表示(如,下單日期維度和支付日志維度中month屬性一個是‘2020-02’表示,一個‘03’表示)。
保證一致性的兩個方法:
- 共享維度表結構:同一實體的不同角色維度表共享一張維度表,通過在核心維度表上創建視圖或進行數據導出實現維度表結構的共享(如:下單日期維度、支付日志維度)。
- 共享維度表內容:其他表加工過程中使用到維度屬性內容,直接從維度表中獲取,該實體的所有屬性,均以維度表中屬性為准,僅在維度表中進行維護,其他事實表/維度表中使用到維度表的指定屬性,僅做內容共享。
4.3 空值處理原則
一個原則:避免空值。 從各業務系統獲取的數據特點各異,同樣在表現在對空值的表示上,“NULL”、“null”、“Null”、“N/A”等等。在構建維度表過程中,需要對此類值做明確的處理,因為進入數據倉庫中經加工的數據是要作為數據資產被應用在各種業務上,不允許出現意義不明確的數據表示,否則這些數據將毫無意義,並且空值在進行數據統計時有時會出現意外的一些統計結果。 維度屬性的數據值,可以通過以下三類區分:有效值、無效值、未知值。用統一明確的標識進行表示(如,“無效值”->“invalid”,“未知值”->“unknown”)。
4.4 命名規范
命名沒有統一的規范,只需要在企業內部有統一規范即可,這樣方便做元數據管理,同樣也能增加開發/業務人員對數據的熟悉程度,能夠“望文生義”,簡單通過表名就能區分數據表。 可以參考以下命名規范: dw.dim_user_info_di
- dw:表示存儲表的物理庫名稱;
- dim(dimension):表示數據倉庫層次划分的維度表層(DIM);
- user_info:表示維度表所表示的業務實體描述;
- di:表示數據表的更新周期,(day increment)日增量更新。
4.5 生命周期管理規范
維度表的存儲周期,一般是越長越好,因為我們不確定什么時候會用到多久的歷史數據,況且數據倉庫本身就是需要存儲歷史數據的。 但在實踐的過程中也同樣發現了一些問題,不少企業在維度表處理上,因其相比事實表數據要小很多,故通常都是將其從業務庫每日進行全量同步,這樣會造成大量的數據冗余。類似情況是必須要對維度表數據最生命周期處理的,否則帶來的成本將遠超其可能解決的業務問題。 而也有一些情況(如,維度表增量更新)在維度表生命周期的處理上要從容很多,增量處理維度表更新,或者通過緩慢變化維處理維度表變化,是又可能將維度表歷史所有數據存儲下來的。當然數據的時效性還是要根據業務的需求進行取舍,調整維度表合適的生命周期,及時清理/歸檔陳舊的歷史數據。