10 分鐘簡讀經典著作 Data Warehouse Toolkit

10 分鐘簡讀經典著作 Data Warehouse Toolkit

數據倉庫(簡稱數倉)是我很感興趣的領域,也是我目前工作職責中重要的部分。想學習這個領域的同學,或許聽過《 Data Warehouse Tookit 》這本由 Ralph Kimball 撰寫的經典著作。不過這是一本超過600頁的大部頭,要啃下來真的要花不少時間。今天就分享一下這本書的核心內容,讓大家了解數據倉庫的一些基本知識。

我看的是這本書第三版的英文原版(2013年出版)。要知道這本書的第一版是1996年出版,經過20多年,雖然有些內容是過時的,但書的核心理念在今天仍適用,很好地演繹了什麼是經典。不過這本書也個缺點,過分追求內容的全面導致有時主次不清,所以有選擇地跳讀是必要的。

帶著問題去讀書可以事半功倍。先說說我讀這本書的背景,在 Glow 我們很重視各類數據的採集,也很喜歡用數據說話。在以前的文章中提過,我們目前用於各類產品分析的 Dashboard 有幾十個,總共包含了上千張圖表。雖然產品經理與分析師們用著還不錯,但我覺得在底層的數據組織上太隨意,沒有一套理論與規範來支撐,長此下去會越搞越亂。讀這本書之前,我知道數據倉庫中最常用的是維度模型,但處於一知半解的狀態。所以我是帶著下面 4 個問題開始看這本書

  • 為什麼維度模型適用於商業分析?
  • 維度模型的基本設計理念是怎樣的?
  • 如何記錄所有的歷史數據與變更?
  • 如何把控數據的質量?

對我來說,這本書的靈魂在第1, 2, 19章,前兩章已經把維度建模的主要方法都介紹了,回答了我的前三個問題。第 3 - 18 章列舉了這套方法在不同行業的實際應用,我根據工作相關性以及興趣,選讀了第3,5,8,14 與 15 章。第 19 章講述了 ETL 中包含的各個子系統,其中有一個部分專門講數據質量的管理,回答了我的第 4 個問題。很佩服 Ralph 老爺子竟然可以在 ETL 中分出 34 個子系統,這也是為什麼我強調這本書不能硬剛,要跳讀。

當然,每個人的問題可能都不太一樣,所以下面還是以科普數據倉庫的基本知識為主脈絡,並在相應的模塊回答之前的那幾個問題。

數據倉庫由哪些部分組成?

在最底層,我們需要將業務場景中的各類數據導入到數據倉庫中,包括業務資料庫、日誌文件、第三方服務數據等等。這一層的目的是將企業的各類數據打通,統一存儲在一個系統中。在這一層我們對源數據的結構只做少量處理。做為數據倉庫最底層的原始數據,它們不應該被分析人員直接查詢。

中間層是數倉的設計者根據業務流程設計的維度模型。由於業務資料庫的主要任務是支持日常業務中的增刪查改,而數據倉庫的主要任務是支持大規模的商業分析。所以數倉底層的原始數據必須轉換為更適合統計分析的維度模型才能發揮價值。我們會在下面的章節中詳細介紹維度模型。

最上層是構建在數倉之上的各類數據應用場景,包括在維度模型上直接進行 Ad-hoc 查詢,建立統計報表,或是做數據挖掘。

若要深入了解,可以閱讀第一章中的 Kimball』s DW/BI Architecture

什麼是維度模型?

維度模型是專為統計分析優化的數據模型,維度模型的設計由業務流程驅動,每一個業務流程對應一張事實表以及若干維度表。在對每項業務做統計分析時,我們所關心的指標記錄在事實表中,如交易金額、利潤、銷售量等。過濾與分組的條件則記錄在維度表中,如交易時間,地區,商品種類等。在事實表的每條記錄中,除了指標數據,還保存連接各維度表的外鍵。這個模型足夠簡單直觀,對於非技術的業務人員來說理解起來也不困難。下圖是一個維度模型的例子

這個模型很好的均衡了查詢複雜度與數據的維護成本。

對於查詢來說,最簡單的模型是一張超寬的業務表,所有的查詢條件都有對應的表內欄位,不需要任何 join 。但壞處是這張表的維護成本很高,有大量的冗餘數據,經常要修改表結構或是現有數據來適應業務的變化。對於資料庫管理員來說,這張表就是一場災難。而經典的 ER 模型是另一個極端,表的維護成本低,沒有冗餘數據,但對於統計查詢不友好。業務人員不但要理解錯綜複雜的表與表之間的網狀關係,而且構建統計查詢的 SQL 語句的難度也很大,還要忍受複雜 SQL 語句低下的執行效率。

維度模型就是這兩者之間的一個折中。對業務人員來說,查詢時有統一的語句結構,並且最多只有一級 join。對維護人員來說,為應對業務需求的變化,大部分數據表的更改都發生在數據量較小的維度表上。這是一個非常棒的設計!

關於維度表的詳細介紹,可以閱讀書中第一章的 Dimensional Modeling Introduction

事實表設計

事實表是維度模型的中樞,在設計事實表時最主要有兩個問題

  • 定義指標
  • 確定每條記錄的粒度

指標大部分情況下都是數字,如果出現文本的指標,則該考慮一下它到底是指標還是維度。在分析統計中,我們會對指標數據做各種聚合,比如計算總和,平均數,中位數等等,根據對聚合操作的支持,我們可以把指標分為可加,半可加與不可加。可加的指標是最好用的,比如交易金額與銷售量。無論如何切分數據,交易金額總和與銷售量總和都是有意義的。半可加的指標只在某些數據切分下可以求總,比如賬戶餘額,在多個賬戶之間可以求總,但若將賬戶以時間維度切分,就總就是沒有意義的。不可加指標的例子包括銷售單價或是稅率。許多時候,半可加或是不可加指標是可以通過可加指標計算得到的,比如銷售單價 = 交易金額 / 銷售數量。在設計事實表中,一個原則就是我們要盡量存儲可加的指標。

事實表中每條記錄的粒度越小,在其之上的統計分析就越精細。所以一般來講,我們都會以業務中最小的原子事務為粒度來構建事實表。比如在常見的購物場景中,最小的粒度並不是一個訂單,而是訂單中的一個子項,即購買某某商品 N 件,所以事實表的每條記錄應是訂單中的一個子項。事實表設計的另一個重要原則是要保證表中每一條記錄的粒度是相同的。比如一個事實表中不能有的記錄是單筆訂單,有的記錄是訂單中的一個子項。因為這樣就破壞了指標的可加性,在過濾條件設置不當時,很容易得出錯誤的統計結果。

除了以事務為粒度的事實表外,另一種常見的類型是周期快照事實表。周期的粒度可以是日,周或是月。它是對一個周期內發生的所有事務聚合得到的。它不能代替事務事實表,但可以讓許多商業分析更快速便捷。畢竟,除了少數分析需要精確到每筆交易,以自然日為粒度的統計可以滿足大部分需求。

有時一個業務的流程需要很多步驟,整個過程會持續較長的時間。比如一次網購,它由下單、付款、貨物發出、簽收等步驟組成,從頭至尾可能要許多天的時間。如果我們要分析每一步到下步之間的時長、流失率等指標,最好的事實表結構是把一次網購的整個流程作為一條記錄保存,各個時間點分別存在該記錄的不同欄位中,這就是累積快照事實表。之前介紹的兩種事實表,一條記錄一旦寫入後,基本不會再被更新,而累積快照事實表的每條記錄在業務流程進行的過程中會被多次更新。值得注意的是,相比插入新記錄,在數據倉庫中完成大批量記錄更新的技術難度會更高。

關於事實表的詳細介紹,可以閱讀書中第二章的 Basic Fact Table Techniques

維度表的設計

維度表用於輔助描述事實發生的場景,為事實增添了 who, what, where, when, how 和 why 這些細節,主要用於過濾與分組。維度屬性設計是數據倉庫質量的關鍵。

乍看之下,維度表和 ER 模型中的 Entity 表有許多相似之處,比如客戶表,商品表等都是很常見的維度表。那麼維度表在設計時,與設計業務資料庫的表有哪些關鍵性的不同呢?

更多使用描述性文字

在業務資料庫中,我們常常用標誌位,布爾值或是操作代碼做為欄位的內容。在維度表,我們更推薦使用描述性的文字。比如,在客戶表中有一個 membership 欄位來表示該客戶是否為會員。在業務表中,該欄位會用布爾型的 0/1 表示。但是在維度表中,該欄位應該為文本型。可以用 Yes/No 做為屬性值,但更好的選擇是用 Member/Non-member 做為屬性值。當你做分組或是透視表時就可以看出差別,由後者產生的報表描述更清晰。

扁平的層級

在業務資料庫中,我們在設計表時會遵循第三範式,盡量避免冗餘,但也會因此產生更多的表與層級,而這恰恰是維度表所要避免的。例如,一個大企業之下會有若干品牌,每個品牌之下有商品分類,每個分類之下再有單類的商品。以 ER 模型的設計思路,品牌,分類以及商品都應該是單獨的表,商品用外鍵連接分類,分類再用外鍵連接品牌。而在設計維度表時,我們應該只建一張商品表,將品牌名,分類名直接保存在商品表中。雖然這會導致大量的數據冗餘,但這張維度表對分析人員來說更簡單易用。

日期維度表

「日期在事實表中用一個欄位存不就好了,有必要做成一個維度表嗎?」這可能是很多人第一次聽到日期維度表時的想法,至少我是這樣。但讀了這本書之後,就覺得日期維度確實有其精妙之處。一年只有365天,所以即使存100年,日期維度表也只有不到 4 萬條記錄。但它除了常規的日、月、年之外,還可以有許多有趣的屬性,可以存星期幾,是工作日還是休息日,是否是法定節日,是哪一個財年,哪一個季度等等。這使你的事實表可以在更豐富的時間維度上做分析,例如對比節假日與非節假日的銷量,或是計算財報等。

關於維度表的詳細介紹,可閱讀第二章的 Basic Dimension Table Techniques。

維度表的更新

在業務資料庫中,當更新一條記錄時,我們一般採用的是覆蓋的方式。雖然在有些維度表上,我們也可以用這種方式,但數據倉庫的一個重要職責就是完整記錄所有的歷史數據。所以這一節我們來談談更新維度表時如何保留歷史,在這本書中給出了 6 種方法,詳情可閱讀第二章中的 Dealing with Slowly Changing Dimension Attributes。

這裡我只介紹一種方法,在書中被稱為 Type 2: Add New Row,也就是為每一次更新創建一條新記錄。這個方法的通用性最強,並且在更新時不用修改事實表。

要使用這個方法,首先在維度表中就不能以自然鍵為主鍵,因為同一個自然鍵可能對應多條記錄。這就需要創建一個代理鍵做為主鍵,可以是一個簡單的自增序列。其次要額外添加三個欄位,分別是記錄的生效日期(Row Effective Date),記錄的失效日期(Row Expiration Date), 以及是否為當前記錄的標誌位(Current Row Indicator)。

在事實表新增記錄時,我們可以通過維度表的自然鍵和當前標誌位來找到對應的維度記錄,將該記錄的代理鍵做為外鍵存入事實表。當維度表更新記錄時,將當前記錄的標誌位置否,記錄失效日期設為當前時間。並增加一條新記錄,新記錄的生效日期為當前時間,失效日期設為一個最大日期的常數,並置上當前標誌位。

要在維度表中查找某個歷史時刻 hist_date 對應的記錄時,只需通過以下 SQL 語句

select * from example_tablewhere hist_date >= row_effective_date and hist_date < row_expiration_date and [other conditions...]

數據質量管理

關於數據質量管理,我非常贊同書中的一句話 「Seemingly small data quality issues are, in reality, important indications of broken business processes」。比如數據錄入的錯誤或是缺失是常見的質量問題,為什麼會出發生這種情況?很可能這些數據的錄入,對於業務人員來說,只是一種負擔,但對他們的工作並沒有幫助,那就說明業務流程出現了問題。

建立一套數據質量管理體系需要 1)建立一組數據質量測試 2)對每條數據,記錄質量審計結果

數據質量測試根據範圍大小可以分為三層

  • 欄位測試最為簡單,比如檢查一個欄位的值是否超出了正常範圍,或是出現了不該有的空值。
  • 結構測試需驗證欄位之間的關係,一個典型的例子是測試外鍵的有效性。(數倉一般不會強制外鍵關係)
  • 商業邏輯測試相對來說更複雜,比如對一家航空公司來說,驗證金牌會員欄位的正確性,需計算該客戶過去一年的總里程數是否超過特定閾值。

有了質量測試之後,要創建一張質量錯誤事實表,記錄每一個質量錯誤,並定期審查。另一方面,無論一條數據是否通過質量測試,我們都可以打上一組質量審計標籤,比如總體質量評分,各類質量錯誤的標誌位,ETL 程序的版本號,ETL 的執行序號等等,這與實體產品生產標籤上的日期與批次號有異曲同工之妙。

在數據倉庫中,質量把控是很重要但又容易被忽略的環節,有興趣深入了解的朋友可閱讀書中第 19 章的 Cleaning and Conforming Data

小結

本文簡讀了《 Data Warehouse Toolkit 》一書中的一些關鍵概念。雖然數據倉庫在實踐中有許多細節,但維度模型的核心理念卻是非常簡單的,所以希望這個簡讀能對大家有所幫助。有什麼建議意見,歡迎留言。


歡迎關注我的微信公眾號:yecomment

推薦閱讀:

如何利用八爪魚,實現餐飲大數據(以辰智商圈秀為例)
相信未來——深度好詩,值得所有心懷希望的人讀!
雲棲大會 | 阿里巴巴 CTO 王堅:城市大腦 —— 數據重塑城市未來
數據分析培訓:一名數據分析師的職場感悟
今日數據行業日報(2016.12.07)

TAG:數據倉庫 | 大數據 |