目錄:
- 維度設計基礎
- 維度的基本概念
- 維度的基本設計方法
- 維度的層次結構
- 規范化和反規范化
- 一致性維度和交叉探查
- 維度設計高級主題
- 維度整合
- 水平拆分
- 垂直拆分
- 歷史歸檔
- 維度變化
- 緩慢變化維
- 快照維表
- 極限存儲
- 微型維度
- 特殊維度
- 遞歸層次
- 行為維度
- 多值維度
- 多值屬性
- 雜項維度
- 數據崗位工作:了解需求 → 模型設計 → ETL 開發 → 測試 → 發不上線 → 日常運維 → 任務下線;
一、維度設計基礎
1、維度的基本概念
- 維度的作用:一般是用來進行查詢約束、分類匯總、排序等操作的;
- 維度建模從分析決策的需求出發構建模型;
- 維度是事實表的組成部分,是對事實表的擴展或進一步解釋說明;
- 在維度建模中,將度量稱為 “事實”,將環境描述為 “維度”,維度是用於分析事實所需要的多樣環境;
- 例:在分析交易過程時,“淘寶交易事務事實表” 中的買家、賣家、商品、時間等維度,以這些維度建立的維表,來描述交易發生的環境,以及對 “淘寶交易事務事實表” 進一步解釋說明;
- “淘寶交易事務事實表” 實例
- 維度屬性:維度所包含的內容,為維度的列;
- 如:上圖中的 “發貨地區維度表” 中的區縣、城市、省份、國家;
- 維度屬性是查詢約束條件、分組、報表標簽生成的基本來源,是數據易用性的關鍵;
- 例1:在查詢請求中,想獲取某類目的商品、正常狀態的商品等信息,是通過約束商品類目屬性和商品狀態屬性來實現的(也就是設定商品類目屬性、商品狀態屬性為查詢條件,來查詢獲取目標信息);
- 例2:統計淘寶不同商品類目的每日成交金額,是通過商品維度的類目屬性進行分組的;
1/1)如何獲取維度或維度屬性?
- 可以在報表中獲取;
- 可以在和業務人員交談中發現維度或維度屬性;
- 因為維度或維度屬性經常出現在查詢或報表請求中的 “按照。。。” 語句中;
- 例:用戶要 “按照” 月份和產品來查看銷售情況;—— 那么用來描述其業務的自然方法應該作為維度或維度屬性包括在維度模型中;
1/2)代理鍵、自然鍵
- 維度使用主鍵標識其唯一性,主鍵也是確保與之相連的任何事實表之間 存在引用完整性的基礎;
- 主鍵有兩種:代理鍵和自然鍵,都是用於標識某維度的具體值;
- 代理鍵是不具有業務含義的鍵,一般用於處理緩慢變化維;
- 自然鍵是具有業務含義的鍵;(自然鍵,一般就是維度在具體業務數據中的名稱或 ID,而且名稱或 ID 在一個業務模塊中是獨有的,沒有跟它相同的)
- 例:上圖 “淘寶交易事務事實表” 中的買家 ID、賣家 ID、商品 ID等,在業務過程中,都具有具體的含義;
- 對於前台應用系統來說,商品 ID 是代理鍵;對於數據倉庫系統來說,商品 ID 屬於自然鍵;
2、維度的基本設計方法
- 維度的設計過程就是確定維度屬性的過程;
- 如,維度 “買家“,其設計過程,就是確定買家的姓名、性別、ID、籍貫等與之相關的信息,也就是其維度屬性;
- 如何生成維度屬性,以及所生成的維度屬性的優劣,決定了維度使用的方便性,是數據倉庫易用性的關鍵;
- Kimball:數據倉庫的能力直接與維度屬性的質量和深度成正比;
2/1)以淘寶的商品維度為例對維度設計方法進行說明:
- 第一步:選擇維度或新建維度;
- 分析需求,選擇維度或新建維度;
- 作為維度建模的核心,在企業級數據倉庫中必須保證維度的唯一性;
- 例:淘寶商品維度,有且只允許有一個維度定義;
- 第二步:確定主維表;
- 此處的主維表一般是 ODS 表,直接與業務系統同步;
- 例:淘寶商品維度,s_auction_auctions 是與前台商品中心系統同步的商品表,此表即是主維表;
- 前端商品系統:為商城、購物車、訂單、營銷活動等提供商品基礎數據支撐;
- 后端商品系統:為供應商管理、采購訂單等提供數據支持;
- 第三步:確定相關維表;
- 數據倉庫是業務源系統的數據整合,不同業務系統或者同一業務系統中的表之間存在關聯性;
- 根據對業務的梳理,確定哪些表和主維表存在關聯關系,並選擇其中的某些表用於生產維表屬性;
- 例:淘寶商品維度,梳理業務邏輯,可以得到商品與類目、SPU、賣家、店鋪等維度存在關聯關系;
- 第四步:確定維度屬性;
- 第一階段:從主維表中選擇維度屬性或生成新的維度屬性;
- 第二階段:從相關維表中選擇維度屬性或生成新的維度屬性;
- 例:淘寶商品維度,從主維表(s_auction_auctions)和相關維表(類目、SPU、賣家、店鋪等)中選擇維度屬性或生成新的維度屬性;
- 確定維度屬性注意事項:
- 盡可能生成豐富的維度屬性;(唯一維度盡量囊括所有相關的維度屬性)
- 如淘寶的商品維度有近百個維度屬性,為下游的數據統計、分析、探查提供了良好的基礎;
- 盡可能多的給出包括一些富有意義的文字性描述;(便於大家理解屬性所指的意思)
- 屬性不應該是編碼,而應該是真正的文字;
- 在阿里的維度建模中,一般是編碼和文字同時存在,如商品維度中的商品 ID、商品標題、類目 ID、類目名稱等;
- ID 一般用於不同表之間的關聯,而名稱一般用於報表標簽;
- 區分數值型屬性和事實;(有的數值是指代,比如 0 、1,有時並不是數值 0 和 1)
- 如果通常用於查詢約束條件或分組統計,數值型字段是作為維度屬性;
- 如果通常用於參與度量的計算,數值型字段則是作為事實;
- 有時即可作為維度屬性使用,由可以作為事實用用:如商品價格,如果用於統計價格區間的商品數,是作為維度屬性使用;如果用於統計某類目下商品平均價格,則是作為事實使用;
- 另外,如果數值型字段是離散的,則作為維度屬性存在的可能性較大;如果數值型字段是連續的,則作為度量存在的可能性較大,但是不絕對;
- 盡量沉淀出通用的維度屬性;(便於大家相互理解)
- 一方面,提高下游使用的方便性,減少復雜性;
- 另一方面:避免下游使用解析時,由於各自邏輯不同而導致口徑不一致;
- 盡可能生成豐富的維度屬性;(唯一維度盡量囊括所有相關的維度屬性)
3、維度的層次結構
- 如果維度中的描述屬性,以層次方式或一對多的方式相互關聯,可以被理解為包含連續主從關系的屬性層次;
- 層次的最底層,代表維度中描述最低級別的詳細信息;層次的最高層,代表最高級別的概要信息;
- 例:淘寶商品維度,有賣家、類目、品牌等,商品屬於類目,類目屬於行業;其中類目的最低級別是葉子類目,葉子類目屬於二級類目,二級類目屬於一級類目;
- 在屬性的層次結構中進行鑽取,是數據鑽取的方法之一;
- 例:假設已有一個淘寶交易訂單,創建事實表;
- 方法:通過向報表中添加連續的維度細節階級,實現在層次結構中鑽取;
- 統計 2015 年 “雙 11 ”的下單 GMV(所有訂單的總金額,包括已付款的和未付款的),得到一行記錄;
- 沿着層次向下鑽取,添加行業,得到行業實例的記錄數;
- 沿着層次向下鑽取,添加一級類目,得到一級類目實例個數的記錄;
4、規范化和反規范化
- 雪花模式:當屬性層次被實例化一系列維度,而不是單一的維度時,被稱為雪花模式;
- 理解,就是以主維度的屬性為維度,建立一些列子維維;(如,下圖 10.1 所示)
- 規范化操作:將屬性層次實例化為一系列維度,而不是單一維度,稱為規范化操作(也即為雪花模式);(產生多個相關聯的表)
- 反規范化操作:將維度的屬性層次合並到單個維度中的操作,稱為范規范化;(將多個相關聯的表整合到一起)
- SPU:標准化商品單元;
- SKU:庫存量單元;
- 例:手機,買的一個紙盒包裝好的標配手機,就是一個 SPU;一個 SKU 可能包含若干個 SPU,比如倉庫里一箱(具體要看倉庫中最小存儲單元是什么)有 20 個手機;
- 例1:雪花模式;
- 例2:反規范化操作;
- 雪花模式的劣勢:
- 更新不便:如例 1,如果更新商品表,則需要更新與之相關聯的所有表;
- 查詢不便:如例 1,如果查詢某具體的商品的詳細信息,則需要查詢與之關聯的所有表中與其有關的信息,然后再整合到一起,需要大量的關聯操作;
- 雪花模式的優點:節約存儲空間;
- 反規范化操作的優點:復雜度低,便於查詢與更新;
- 大多數聯機事務處理系統(OLTP)的底層數據結構,在設計時采用雪花模式技術,通過規范化處理將重復屬性移至其自身所屬的表中,刪除冗余數據;
5、一致性維度和交叉探查
5/1)交叉探查
- 定義:將不同數據域的商品的事實合並在一起進行數據探查,如計算轉化率等,稱為交叉探查;(兩個數據域叫的實時放一起分析)
- 能夠進行交叉探查的條件:進行交叉探查的兩個維度屬性(隸屬於兩個維度),必須相同,且屬性值的格式也一致;
- Kimball 構建企業級數據倉庫方法:通過構建企業范圍內一致性維度和事實,來構建總線架構;
- 一致性維度,是數據倉庫總線架構的重要基石之一;
- 在針對不同數據域進行迭代構建或並行構建時,存在很多需求,是對不同數據域的業務過程,或者同一數據域的不同業務過程,合並在一起觀察;
- 例:對於日志數據域,統計了商品維度的最近一天的 PV 和 UV;對於交易數據域,統計了商品維度的最近一天的下單 GMV;如果要對兩個數據域並行構建,則需要將PV、UV、GMV 合並在一起進行數據探查;
5/2)一致性維度
- 不同數據域的維度不一致,不能進行交叉探查;
- 維度不一致:維度屬性不一致、維度屬性一致但維度屬性的值的格式不一致、維度屬性及其值的格式都不一致(如維度屬性時間:yy-MM-dd、UNIX timestamp,格式不一致);
- 情景:假設對於日志數據域,統計使用的是商品維度 1;對於交易數據域,統計使用的是商品維度 2;
- 維度屬性不一致:商品維度 1 包含維度屬性 BC 類型,而商品維度 2 無此屬性,則無法在 BC 類型上進行交叉探查;
- 維度屬性移至但屬性值不一致:商品維度 1 的商品上架時間,這一維度屬性的時間格式是 yyy-MM-dd HH : mm : ss,商品維度 2 的商品上架時間這一維度屬性的時間格式是 UNIX timestamp,進行交叉探查時,如果需要根據商品上架時間做限制,則復雜性較高;
- 維度一致性的幾種表現形式:
- 共享維表;
- 如,阿里的數據倉庫中,商品、賣家、買家、類目等維度有且只有一個,在基於這些公共維度進行的交叉探查不會存在問題;
- 一致性上卷:一個維度的維度屬性,是另一個維度的維度屬性的子集,且兩個維度的公共維度屬性結構和內容相同;
- 如,阿里的商品體系中,有商品維度和類目維度,其中類目維度的維度屬性是商品維度的維度屬性的子集,且有相同的維度屬性和維度維護性值,這樣基於類目維度進行不同業務過程的交叉探查不會存在問題;
- 交叉屬性:像個維度具有部分相同的維度屬性;
- 如,在商品維度中具有類目屬性,在賣家維度中具有主營類目屬性,兩個維度具有相同的類目屬性,則可以在相同的類目屬性上進行不同業務過程的交叉探查;
- 共享維表;
二、維度設計的高級主題
1、維度整合
- 數據倉庫定義:是一個面向主題的、集成的、非易失的、隨時間變化的數據集合,用來支持管理人員的決策;
- 集成性是數據倉庫四大特性中最重要的一個;
- 主題:不同的應用環境,或者不同的業務模塊;
- 數據倉庫的重要數據來源,是大量的、分散的、面向應用的操作型環境;
- 不同的應用在設計過程中,可以自由決策,主要滿足本應用的需求,很少會考慮和其他系統進行數據集成;
1/1)應用間的差異表現在如下幾個方面
- 應用在編碼、命名習慣、度量單位等方面存在很大差異;
- 如,不同應用對性別編碼不同:有 0 和 1、有 F 和 M 等;
- 如,不同應用的用戶 ID 含義相同,但字段名稱不同:user、user_id 等;
- 如,不同應用對於金額的度量單位不同:元、分等;
- 應用出於性能和擴展性的考慮,或者隨技術架構的演變,以及業務的發展,采用不同的物理實現;拆分至不同類型數據庫中,部分數據采用關系型數據庫(如 Oracle、MySQL 等),部分數據采用 NoSQL 數據庫存儲(如 HBase、Tair 等);拆分成同一類型數據庫中的多個物理表;
- 如,淘寶商品,有商品主表和商品擴展表,商品主表存儲商品基本信息,商品擴展表存儲商品特殊信息,如不同產品線的定制化信息等;
- 如,淘寶會員,有會員主表和會員擴展表,會員主表存儲用戶基本信息,會員擴展表存儲用戶擴展信息,如用戶的各種標簽信息等;
1/2)數據集成
- 由於應用間的差異,數據有面向應用的操作型環境進入數據倉庫后,需要進行數據集成;
- 將面向應用的數據,轉換為面向主題的數據倉庫數據,本身就是一種集成,具體體現在日下幾個方面:
- 制作單張表時規范統一(如下 1、2、3 方面)、在整合多張表時規范統一(如下 第 4 方面);
- 名規范的統一:表名、字段名等統一;
- 字段類型統一:相同和相識字段的字段類型統一;
- 公共代碼及代碼值的統一:公共代碼及標志性字段的數據類型、命名方式等統一;
- 業務含義相同的表的統一
- 高內聚、低耦合理念:將業務關系大、源系統影響差異小的表進行整合;將業務關系小、源系統影響差異大的表進行分而置之;
- 制作單張表時規范統一(如下 1、2、3 方面)、在整合多張表時規范統一(如下 第 4 方面);
-
常用集成方法:
- 采用主從表的設計方式
- 將兩個表或多個表都有的字段放在主表中(主要基本信息),從屬信息分別放在各自的從表中;
- 對於主表中的主鍵,要么采用復合主鍵、源主鍵和系統或表區別標志,要么采用唯一主鍵、“源主鍵或表區別標志” 生成新的主鍵;通常采用復合主鍵;
- 直接合並:共有信息和個性信息都放在同一個表中;
- 注意:如果表字段的重合度較低,則會出新大量空值,對於存儲和易用性有影響,需謹慎選擇;
- 不合並
- 源表的結構及主鍵差異很大,無法合並,使用數據倉庫的多個表存放各自的數據;
1/3)表級別的整合
- 表級別的整合,有兩種表現形式:
- 第一種是垂直整合:不同的來源表包含相同的數據集,只是存儲的信息不同;
- 如,淘寶會員在源系統中有多個表,會員基礎信息表、會員擴展信息表、淘寶會員等級信息表、天貓會員等級信息表,這些表都屬於會員的相關信息表,依據維度設計方法,盡量整合至會員維度模型中,豐富維度屬性;
- 第二種是水平整合:不同的來源表包含不同的數據集,不同子集之間無交叉,也可以存着部分交叉;
- 如,螞蟻金服的數據倉庫,其采集的會員數據有淘寶會員、1688 會員、國際站會員、支付寶會員等,是否需要將所有的會員整合到一個會員表中?如果進行整合:
- 如果各個會員體系有交叉,需要去重;
- 如果各個會員體系沒有交叉,需要考慮不同子集的自然鍵是否存在沖突,如果不沖突,則可以考慮將各子集的自然鍵作為整合后的表的自然鍵;或者,設置超自然鍵,將來源表各子集的自然鍵加工成一個字段作為超自然鍵;(在阿里,通常采用將來源表各子集的自然鍵作為聯合主鍵的方式,並且在物理實現時將來源字段作為分區字段。)
- 如,螞蟻金服的數據倉庫,其采集的會員數據有淘寶會員、1688 會員、國際站會員、支付寶會員等,是否需要將所有的會員整合到一個會員表中?如果進行整合:
- 第一種是垂直整合:不同的來源表包含相同的數據集,只是存儲的信息不同;
2、水平拆分
2/1)維表分析
- 維度通常可以按照類別或類型進行細分:
- 情景 1:淘系商品表,根據業務線或行業可以對商品細分:淘寶商品、天貓商品、1688 商品、飛豬旅行商品、淘寶海外商品、天貓國家商品等;
- 不同分類的商品,其維度屬性可能相同,也可能不同:
- 情景 2:航旅的商品和普通淘系商品,都屬於商品,都有商品價格、標題、類型、上架時間、類目等維度屬性,但是航旅的商品除了公共屬性,還有酒店、景點、門票、履行等自己獨特的維度屬性;
2/2)如何設計維度
- 思路:根據上述分析的維表數據情景,反向思考維度設計方案;
- 方案一:將維度的不同分類實例化為不同的維度,在主維度中保存公共屬性,在擴展子維度中存放獨特的維度屬性;
- 方案二:維護單一維度,包含所有可能的屬性;
- 維度設計考慮原則:
- 擴展性:當源系統、業務邏輯變化時,能通過較少的成本快速擴展模型,保持核心模型的相對穩定性;(高內聚、低耦合為重要指導思想;)
- 效能:在性能和成本方面取得平衡;(通過犧牲一定的存儲成本,達到性能和邏輯的優化)
- 易用性:模型可理解性高、訪問復雜度低;(方便用戶從模型中進行數據查詢和分析)
2/3)如何拆分維度
- 思路:根據上述維度設計的過程,反向思考維度拆分依據;
- 維度的不同分類的屬性的差異情況;(有些屬性相同或相識,有些維度差異很大)
- 定義一個主維度存放公共屬性、定義多個子維度存放公共屬性和各自的獨特屬性;
- 業務的關聯程度;
- 兩個相關性較低的業務,分別建立維度;
- 相關性較低的業務:具有各自的數據集市,一般不相互調用,業務分析人員一般只針對本數據集市進行統計分析;
3、垂直拆分
- 維度屬性的豐富程度決定了數據倉庫的能力;
- 能力:快速組織和存儲數據、快速查詢和分析數據
- 出於擴展性、產出時間、易用性等方面考慮,設計主從維度:主維表存放穩定、產出時間早、熱度高的屬性,從維表存放變化較快、產出時間晚、熱度低的屬性;
- 由於商品有擴展冗余的庫存等變化較快的數據,對於主維度進行緩慢變化的處理較為重要;
- 通過存儲的冗余和計算成本的增加,實現了商品主模型的穩定和產出時間的提前,對於整個數據倉庫的穩定和下游應用的產出都有較大意義;
4、歷史歸檔
- 歸檔:將歷史數據歸檔至歷史維表中;
- 前台歸檔方法:如,將商品狀態為下架或刪除的、且最近 31 天內未更新的商品,歸檔至歷史庫;具體邏輯根據不同 BU,有不同的算法,且有特殊的規則;
-
數據倉庫中的歸檔策略:
- 歸檔策略 1:同前台歸檔策略,在數據倉庫中實現前台歸檔算法,定期對歷史數據進行歸檔;
- 問題 1:前台歸檔策略復雜,實現成本較高;
-
問題 2:前台歸檔策略坑能會經常變化,導致數據倉庫歸檔算法也要隨之變化,維護和溝通成本較高;
-
總結:此方案使用於前台歸檔策略邏輯較為簡單,且變更不頻繁的情況;
- 歸檔策略 2:同前台歸檔策略,但采用數據庫變更日志的方式;
-
通過數據庫 binlog 日志解析獲取每日增量;
-
通過增量的 merge 全量的方式獲取最新的全量數據;
-
使用增量日志的刪除標志,作為前台數據歸檔的標志,通過此標志對數據倉庫的數據進行歸檔;
-
總結:不需要關注前台歸檔策略,簡單異性,但對前台應用的要求是,數據庫的物理刪除只有在歸檔時才執行,應用中的刪除只是邏輯刪除;
-
- 歸檔策略 3:數據倉庫自定義歸檔策略;
- 將歸檔算法用簡單直接的方式實現,但要盡量比前台應用歸檔晚、少歸檔,避免出現數據倉庫中已經歸檔的數據再次更新的情況;
- 歸檔策略 1:同前台歸檔策略,在數據倉庫中實現前台歸檔算法,定期對歷史數據進行歸檔;
- 歸檔策略總結:如果技術允許,能夠解析數據庫 binlog 日志,使用歸檔策略 2,規避前台歸檔算法;
三、維度變化
1、緩慢變化維
- 背景:現實世界中,維度的屬性並不是靜態的,會隨着時間的流逝發生緩慢變化(如,VIP / 信譽 等級);(指屬性值的變化)
-
處理緩慢變化維的 3 種方式(由 Kimball 提出):
- 實例進行說明:商品所屬的類目於 2015 年 11 月 16 日,由類目 1 變成類目 2:
-
方式 1:重寫維度值;
- 特點:不保留歷史數據,始終取最新數據;
-
方式 2:插入新的維度行
-
特點:保留歷史數據,維度值變化前的事實和過去的維度值關聯,緯度值變化后的事實和當前的緯度值關聯;
-
問題:不能將變化前后記錄的事實,歸一為變化前的維度或者歸一為變化后的維度;
-
解釋:因為插入新的維度行,相當於給維表添加新的商品,與維度屬性變化前的商品,算做兩種商品,那么事實表中也會添加新種類商品的數據;其實 “兩種“ 商品只是某一屬性或某幾個屬性不一樣而已,其它屬性完全一樣,如果想對 “兩種” 商品的歷史數據進行統一統計時,此方法不便實現;
-
- 方式 3:添加維度列;
- 總結:選擇哪種方式處理緩慢變化維,要根據業務需求進行選擇;
2、快照維表
- Kimball 的維度建模理論中,必須使用代理鍵作為每個維表的主鍵,用於處理緩慢變化維;
2/1)阿里內部采用維度建模,但不使用代理鍵:
- 分布式計算系統 MaxCompute,生成穩定的、全局唯一的代理鍵的難度較大;
- 此處的穩定指,某條記錄每次生成的代理鍵都相同;
- 使用代理鍵會大大增加 ETL 的復雜性,對 ETL 任務的開發和維護成本很高;
2/2)不使用代理鍵處理緩慢變化維
- 采用快照方式,處理緩慢變化維;
- 操作方式:
- 以數據倉庫計算周期為頻率,保留一份每一周期內的全量快照數據;(全量快照數據是按全量存儲方式存儲的)
- 限定日期,任意周期的事實快照和維度快照通過維度的自然鍵進行關聯;
-
例:商品維度;
- 每天保留一份全量商品快照數據,任意一天的事實均可獲取到當天的商品信息,也可以獲取到最新的商品信息,通過限定日期,采用自然鍵進行關聯即可;
-
優點:
- 簡單有效,開發和維護成本低;
- 使用方便,理解性好;(數據的使用方只需要限定日期,即可獲取當天的快照數據,任意一天的事實快照與維度快照,通過維度的自然鍵進行關聯即可)
- 弊端:極大浪費存儲;
- 總結:此方法就是犧牲存儲獲取 ETL 效率的優化和邏輯上的簡化;但是,杜絕過度使用此方法,而且必須要限定數據的生命周期,清除無用的歷史數據;
3、極限存儲
3/1)歷史拉鏈存儲
- 思想:在每個數據倉庫計算周期內,只記錄變化的數據,對於不變的數據不再重復記錄;
- 歷史拉鏈存儲:利用維度模型中緩慢變化維的第二種處理方式;(插入新的維度行)
- 操作方式:新增兩個時間戳字段( start_dt 和 end_dt ),將所有以天為粒度(數據倉庫計算周期)的變更數據,都記錄下來;
- 通常分區字段也是時間戳字段;
- 例:2016 年 1 月 1 日,賣家 A 在淘寶上發布了 B、C 兩個商品,前端商品表將生產兩條記錄 t1、t2;1 月 2 日,賣家 A 將 B 商品下架了,同時發布了商品 D ,前端商品表將更新記錄 t1,有新生成記錄 t3;
- 采用全量存儲方式:在 1 月 1 日分區中存儲 t1、t2 兩條記錄;在 1 月 2 日分區中存儲更新后的 t1、t2、t3 記錄;
- 采用歷史拉鏈存儲:對於不變的數據,不再重復存儲;
- 下游應用只需要限制時間戳字段來獲取歷史數據;(例:用戶訪問 1 月 1 日的數據:start_dt <= 20160101 和 end_dt > 20160101 )
- 采用全量存儲方式:在 1 月 1 日分區中存儲 t1、t2 兩條記錄;在 1 月 2 日分區中存儲更新后的 t1、t2、t3 記錄;
-
歷史拉鏈存儲弊端:
- 不變下游工作人員理解;(特別是 ODS 數據面向的下游用戶,包括數據分析師、前端開發人員等;他們不怎么理解數據模型的概念)
- 使用 start_dt 和 end_dt 做分區,隨着時間的推移,分區數量會越來越多,而現行的數據庫系統都有分區數量限制;
3/2)極限存儲
- 在歷史拉鏈存儲的基礎上完善,步驟:
- 透明化
- 底層的數據使用歷史拉鏈存儲方式;
- 在上層做一個視圖操作,或者在 Hive 里做一個 hook;
- 視圖操作 / hook 的目的:通過分析語句的語法樹,把對極限存儲前的表(歷史歷練表在一個周期的初期,也就是拉鏈存儲周期第一天的全量數據)的查詢,轉換成對極限存儲表的查詢;
- 極限存儲表:一個拉鏈存儲周期內,歷史拉鏈存儲方式存儲的數據;
- 極限存儲前的表:一個拉鏈周期初始時的全量數據;
- 對於下游用戶來說,極限存儲表和全量存儲方式是一樣的:
- 例:查詢 20160101 的數據;
- 視圖操作 / hook 的目的:通過分析語句的語法樹,把對極限存儲前的表(歷史歷練表在一個周期的初期,也就是拉鏈存儲周期第一天的全量數據)的查詢,轉換成對極限存儲表的查詢;
- 做歷史拉鏈表:按周期記錄變化的數據;
- 設置歷史拉鏈表周期;
- 假設以 start_dt 和 end_dt 做分區,每月月初重新做歷史拉鏈表,則表的結構為:
-
1 天為最小分區區間,31 天最長分區區間,1 個月中可能有:30 x 31 / 2 = 465 個分區;(則一年最多可能產生的分區數:465 x 12 = 5580 )
-
1002 產生且 1003 死亡記錄:采用歷史拉鏈存儲方式,從第 2 天到第 3 天的存儲數據;
-
1001 產生且 1031 死亡記錄:采用歷史拉鏈存儲方式,從第 1 天到第 31 天的存儲數據;
-
疑問:每月 1 日的全量數據是什么?
-
- 對極限存儲做額外處理:
-
在做極限存儲前有一個全量存儲表,僅保留最近一段時間的全量分區數據,歷史數據通過映射方式關聯到極限存儲表;(用戶只訪問全量存儲表,通過映射,關聯到極限存儲表,得到最新的變更的全量數據;)(極限存儲表對用戶是不可見的)
-
對變化頻率較高的字段需要過濾;
- 方法一:垂直拆分維度,主維表 + 子維表;
- 方法二:創建微型維度,主維表 + 子維表;
-
- 極限存儲方式的優點:即壓縮了存儲成本,又達到對下游用戶透明的效果;
- 極限存儲方式的弊端:
- 產出效率很低:大部分極限存儲通常需要 t-2;
- 對於變化頻率高的數據,不能達到節約成本的效果;
4、微型維度
4/1)創建微型維表
- 作用:對極限維度的完善;(處理被過濾出的高頻字段)
- 創建微型維度:將一部分不穩定的屬性從主維度中移出,放置到擁有自己代理鍵的新表中,這個新表就是微型維表;
- 微型維表的數據:所有屬性的可能值的排列組合,是固定的數據;(並不是記錄每次屬性的變化值)
- 例:用戶 VIP 等級和用戶信用評價等級,會隨着用戶行為不斷變化。其中,VIP等級共有 0 ~ 8,9 個值;信用等級有 10 個值。假設基於 VIP 等級和用戶信用等級構建微型維度,則在微型維度中共有 9 x 10 個組合,即 90 條記錄,代理鍵可能是 1~90;
- 微型維度中,屬性間沒有直接關聯,不存在自然鍵,只能使用代理鍵;
- 例:淘寶交易事實表,其它維度忽略,星形模式可能表示如下圖;
4/2)阿里數據倉庫不使用微型維度技術
- 微型維度的局限性;
- 微型維度是事先用所有可能值的組合加載的,需要考慮每個屬性的基數,且必須是枚舉類型;但很多屬性可能是非枚舉類型,比如數值類型,如 VIP 分數、信用分數等;時間類型,如上架時間、下架時間、變更時間等;
- ETL 邏輯復雜;
- 對於分布式系統,生成代理鍵和使用代理鍵進行 ETL 加工都非常復雜,ETL 開發和維護成本過高;
- 破壞了維度的可瀏覽性;
- 如,買家維度和微型維度通過事實表建立聯系,無法基於 VIP 等級、信用等級進行瀏覽和統計。(可以在買家維度中添加引用微型維度的外鍵來解決,但帶來的問題是微型維度未維護歷史信息;)
四、特殊維度
1、遞歸層次
- 遞歸層次:維度屬性以層次方式或一對多的方式相互關聯;
- 例:典型的就是商店的商品分類表,一層層的向下細分;(蔬菜水果 → 蔬菜 → 葉菜類 / 根莖類 / 茄夾類)
- 維度的遞歸層次,按照層級是否固定,分為均衡層次結構和非均衡層次結構;
- 均衡層次結構:層級固定;(如,地區,有固定數量的級別 —— 國家、省份、城市、區縣、鄉鎮 / 街道,並且級別間的關系是固定的)
- 非均衡層次機構:層級不固定;(如,公司之間的關系,每個公司可能存在一個母公司,但可能沒有固定的一級、二級等層次關系;)
- 例:淘寶交易事實表通過葉子類目和類目維表關聯,統一類目 ID 為 21 的最近一天的 GMV:
- 獲取父類目 ID 為 21 的所有類目,稱為子類目;
- 判斷子類目是否為葉子類目,如果是葉子類目,則終止;如果不是,以此類目 ID 為父類目 ID,執行第一步操作,知道找到所有的葉子類目;(需要遞歸查找)
- 將所有葉子類目和交易事實表關聯,進行統計匯總,即可得到類目 ID 為 21 的最近一天的 GMV;
-
業務難題:由於很多數據倉庫系統和商業智能工具不支持遞歸 SQL,並且用戶使用遞歸 SQL 的成本較高,所以在維度模型中,需要對遞歸層次結構進行處理:
1/1)層次結構扁平化
- 目的:降低遞歸層次使用復雜度;
- 扁平化操作:建立維度的固定數量級別的屬性;(也就是列舉出所有的層級)
- 如果高層級類目下沒有低層級類目,也就是其本身是葉子類目,則低層級類目置為空值;
- 使用於均衡層次結構;(均衡層次結構層級固定)
- 例:淘寶商品類目,扁平化操作后如下圖:
- 需求:統計類目 ID 為 21 的最近一天的 GMV;
- 將淘寶交易事實表,通過葉子類目和類目維表(扁平化后的類目維表)的類目 ID 關聯,限制一級類目 ID 等於 21,之后進行匯總統計;
-
層次結構扁平化過程中需要解決的問題:
- 針對某類目上鑽或下鑽之前,必須知道其所屬的類目層級,才能決定限制哪一級別類目;(如,類目 ID 等於 21,需要先知道其為哪一級別的類目,才能在關聯時進行限定)
- 如果分五級類目,而有些葉子類目直接是一級類目或二級類目,其后面的為空值,如果限定三級類目統計 GMV,和交易事實表關聯后,這些葉子類目為一級或二級類目的交易無法被統計到;
- 扁平化僅包含固定數量的級別,對於非平衡層次結構,可以通過預留級別的方式來解決,但擴展性較差;
-
解決方法:
- 在進行數據統計前,在類目層級結構扁平化時,對空值進行回填,將類目向下虛擬;(例:如下圖)
1/2)層次橋接表
-
層次橋接表:
- 從高層到底層,以所有層次的屬性作為父類,以與父類本身和比父類低層級的類,作為子類目;(不能用與父類同層級或者比父類層級高的類做子類)
-
例:
- 數據存儲實例:
-
-
橋接表:
- 類目層級間隔:父類目與其子類間的層級差;
-
解決的問題:
- 不需要預先知道所屬層級、不需要回填、可解決非均衡層次結構;
- 步驟:
- 建立層級樹;
- 根據層級樹建立層次橋接表;
- 例 1:對類目 21 進行下鑽操作
- 限制類目表的類目 ID 等於 21 ,通過類目 ID 和類目橋接表的父類目 ID 關聯,使兩表建立連接;(得到部分類目橋接表:類目 21所在層級及其以下所有的類目橋接表)
- 通過類目橋接表(步驟 1 得到的類目橋接表)的子類目 ID 和事實表的類目 ID 關聯,使兩表建立連接;
- 例 2:對類目 50026579 進行上鑽操作
- 限制類目表的類目 ID 等於 50026579,通過類目 ID 和類目橋接表的子類目 ID 關聯,使量表建立連接;
- 通過類目橋接表的父類目 ID 關聯,使量表建立連接;
- 弊端:加工邏輯復雜,使用邏輯復雜,而且由於橋接表和事實表的多對多關系,有雙重計算的隱患;
2、行為維度
2/1)定義
- 行為維度 / 事實衍生維度:通過從從事實中分析得到的維度;(常用到的詞有:主營、主要、常用等)
- 例:
- 賣家主營品牌:需要從賣家的商品分布和交易情況中,分析得出一個賣家的主營品牌;
- 用戶常用地址:需要從賣家發貨地址和買家收貨地址中,分析得到一個買家 / 用戶經常使用的地址是什么;
2/2)分類
- 另一維度的過去行為
- 如,買家最近一次訪問淘寶的時間、買家最近一次發生淘寶交易的時間等;
- 快照事實行為維度
- 如,買家從年初截止當前的淘寶交易金額、買家信用分值、賣家信用分值等;
- 分組事實行為維度,將數值型事實轉換為枚舉值
- 如,買家從年初截至當前的淘寶交易金額按照金額划分的等級、買家信用分值按照分數划分得到的信用等級;
- 復雜邏輯事實行為維度,通過復雜算法加工或多個事實綜合加工得到;
- 如,賣家主營類目,商品熱度根據訪問、收藏、加入購物車、交易等情況綜合計算得到;
2/3)處理行為維度的方式
- 方式 1:將行為維度冗余至現有的維表中;
- 如,將賣家信用等級冗余到賣家維表中;
- 方式 2:加工成單獨的行為維表;
- 如,賣家主營類目,作為單獨的行為維表;
2/4)處理行為維度遵循的原則
- 原則 1:避免維度過快增長;
- 如,對商品表進行了極限存儲,如果將商品熱度加入到現有的商品維表中,由於商品熱度屬性變更頻道較高,可能會使每日商品變更占比過高,從而導致極限存儲效果差;
- 原則 2:避免耦合度過高;
- 如,賣家主營類目,加工邏輯異常復雜,如果融合進現有的賣家維度中,那么過多的業務耦合會導致賣家維表刷新邏輯復雜、維護性差、產出延遲;
3、多值維度
3/1)什么是多為維度
- 對於多只維度,一種情況是,事實表的一條記錄在某維表中有多條記錄與之對應;
- 如,淘寶交易訂單,買家一次購買了多種商品;
- 一次購買交易,作為交易父訂單;
- 對於一次交易中的所有商品的購買,稱為交易子訂單;
- 設計交易父訂單時,對於此事實表的每一條記錄,在商品表中都有一到多條記錄與之對應;
- 如,淘寶交易訂單,買家一次購買了多種商品;
3/2)3 種方式處理多只維度
- 根據業務的表現形式和統計分析需求進行選擇;
- 方式 1:降低事實表粒度
- 適用場景:行為事實可拆分;
- 如,淘寶交易中,前台業務和商業智能關注的是交易子訂單;
- 那么在數據倉庫模型設計中,要將交易設計為子訂單粒度,對於每個子訂單,只有一種商品與之對應;
- 對於事實,將交易數據分攤到子訂單;
- 方式 2:采用多字段
- 適用場景:行為事實不可拆分;
- 如,房產銷售,合同簽訂時可能有多個買方,如夫妻合買;
- 一條合同記錄對應多個買方,而合同未事實中的最細粒度;
- 一般合同的買方不會太多,所以可采用多字段方式;
- 考慮到擴展性(以防可能追加多個買方),可以預留字段;
- 方式 3:采用通用的橋接表
- 場景:所有多值維度情況;
- 操作:在事實表和維表之間開發一個分組表,通過此分組表建立連接;
- 分組 KEY:用於關聯事實表,以及作為買受方維表外鍵的買受方 ID;
- 如果事實表的一條記錄對應 2 各受買方,則橋接表對這 2 各受買方建立兩條記錄,分組 KEY 相同;
-
雙重計算風險:
- 雙重計算不一定是錯誤,要根據業務需求情況而定;
- 例:需求——根據買方籍貫統計某一年的合同總金額;
- 如果兩個買受方的籍貫分別杭州和蘇州,那么此合同的總金額將會被分別到杭州和蘇州,造成雙重計算;
4、多值屬性
4/1)什么是多值屬性
- 多值屬性:維表中的某個屬性同時有多個值;
- 多值屬性是多值維度的另一種表現形式;
- 例:商品 SKU 維表(一般就是指庫存)、商品屬性維表、商品表橋維表等;
- 每個商品均有一到多個 SKU、一到多個屬性和一到多個標簽,所有商品和 SKU、屬性、標簽都是多對多的關系;
4/2)3 種方式處理多種屬性
-
根據具體情況進行選擇:
- 方式 1:保留維度主鍵不變,將多值屬性放在維度的一個屬性字段中;(通過 k-v 對形式,存放在一個屬性中)
- 如,商品屬性(業務中的商品屬性,與維度模型中的維度屬性含義不同),可以通過 k-v (key - value)對的形式放在 property 字段中——10281239 :156426871;137369765:29229;
- 特點:擴展性好,但數據使用麻煩;
- 方式 2:保留維度主鍵不變,將多值屬性放在維度的多個屬性字段中;(每個值作為一個屬性,分成多個屬性存儲)
- 如,賣家主營類目,賣家可能同時賣男裝、女裝、內衣等多種類型,所有賣家主營類目可能有多個;
- 業務要求:賣家主營類目 TOP3;
- 維度的多值屬性字段具體值是數量固定(3 個),可以采用多個屬性字段進行存儲,方便數據統計分析和報表展示;
- 多值屬性字段具體值的數量不固定,可以采用預留字段的方式;
- 如,賣家主營類目,賣家可能同時賣男裝、女裝、內衣等多種類型,所有賣家主營類目可能有多個;
- 方式 3:維度主鍵發生變化,一個維度值存放多條記錄;
- 如,商品 SKU 維表,對於每個商品,有多少 SKU 就有多少條記錄,主鍵是商品的 ID 和 SKU 的 ID;
- 優劣:擴展性好,使用方便,但是需要考慮數據的急劇膨脹情況;
5、雜項維度
- 雜項維度(Junk Dimension):有操作型系統中的指示符或者標志字段組合而成的,一般不在一致性維度之列;
- 理解:雜項,顧名思義,一些其它的非主要屬性;
- 如,淘寶交易訂單的交易類型字段,包括話費充值、司法拍賣、航旅、支付狀態、物流狀態等,它們在源系統中直接保存在交易表中;
- 背景:一個事實表中可能會存在多個非主要屬性數據的字段;
- 如果將它們作為事實存放在事實表中,會導致事實表占用空間過大;
- 如果單獨建立維表,外鍵關聯事實表,則會出現維度過多;
- 如果將它們刪除,但有些人會需要;
- 建立雜項維表:
- 使用多個雜項屬性的字段的不同取值,組成一條記錄,生成代理鍵,存入維表中,並將該代理鍵保存到相應的事實表字段下;
- 建議:不要直接使用所有的組合生成完整的雜項維表,而是在抽取到新的組合時,生成響應的記錄即可;
- 在分布式計算系統中,由於生成代理鍵較為復雜,一般在邏輯模型中,使用實體的主鍵作為雜項維度的主鍵;
- 子訂單維度一般是邏輯模型,物理實現時不進行物理化;
- 訂單雜項維度和其他維度一起,會將維度屬性退化至事實表中;