本文翻譯自“Dimensional Modeling and Kimball Data Marts in the Age of Big Data and Hadoop”,翻譯已獲得原作者 Uli Bethke 授權(quán)。Uli Bethke 是 Sonra 公司的 CEO,愛爾蘭 Hadoop 用戶組主席,也是 Oracle 的 ACE。
維度建模已死?
在回答這個(gè)問題之前,讓我們回頭來(lái)看看什么是所謂的維度數(shù)據(jù)建模。
為什么需要為數(shù)據(jù)建模?
有一個(gè)常見的誤區(qū),數(shù)據(jù)建模的目的是用 ER 圖來(lái)設(shè)計(jì)物理數(shù)據(jù)庫(kù),實(shí)際上遠(yuǎn)不僅如此。數(shù)據(jù)建模代表了企業(yè)業(yè)務(wù)流程的復(fù)雜度,記錄了重要的業(yè)務(wù)規(guī)則和概念,并有助于規(guī)范企業(yè)的關(guān)鍵術(shù)語(yǔ)。它清晰地闡述、協(xié)助企業(yè)揭示商業(yè)過(guò)程中模糊的想法和歧義。此外,可以使用數(shù)據(jù)模型與其他利益相關(guān)者進(jìn)行有效溝通。沒有藍(lán)圖,不可能建造一個(gè)房子或橋梁。所以,沒有數(shù)據(jù)模型這樣一個(gè)藍(lán)圖,為什么要建立一個(gè)數(shù)據(jù)應(yīng)用,比如數(shù)據(jù)倉(cāng)庫(kù)呢?
為什么需要維度建模?
維度建模是數(shù)據(jù)建模的一種特殊方法。維度建模有兩個(gè)同義詞,數(shù)據(jù)集市和星型結(jié)構(gòu)。星型結(jié)構(gòu)是為了更好地進(jìn)行數(shù)據(jù)分析,參考下面圖示的維度模型,可以有一個(gè)很直觀的理解。通過(guò)它可以立即知道如何通過(guò)客戶、產(chǎn)品、時(shí)間對(duì)訂單進(jìn)行分割,如何通過(guò)度量的聚集和比較對(duì)訂單業(yè)務(wù)過(guò)程進(jìn)行績(jī)效評(píng)估。
維度建模最關(guān)鍵的一點(diǎn),是要定義事務(wù)性業(yè)務(wù)過(guò)程中的最低粒度是什么。如果切割或鉆入數(shù)據(jù),到葉級(jí)就不能再往下鉆取。從另一個(gè)角度看,星型結(jié)構(gòu)中的最低粒度,即事實(shí)和維度之間沒有進(jìn)行任何聚集的關(guān)聯(lián)。
數(shù)據(jù)建模和維度建模
標(biāo)準(zhǔn)數(shù)據(jù)建模的任務(wù),是消除重復(fù)和冗余的數(shù)據(jù)。當(dāng)數(shù)據(jù)發(fā)生變化時(shí),我們只需在一個(gè)地方修改它,這有助于保證數(shù)據(jù)的質(zhì)量,避免了不同地方的數(shù)據(jù)不同步。參考下面圖示的模型,它包含了代表地理概念的幾張表。在規(guī)范化模型中,每個(gè)實(shí)體有一個(gè)獨(dú)立的表,數(shù)據(jù)建模只有一張表:geography。在這張表中,city 會(huì)重復(fù)出現(xiàn)很多次。而對(duì)于每個(gè) city,如果 country 改變了名字,就不得不在很多地方進(jìn)行更新。
注:標(biāo)準(zhǔn)數(shù)據(jù)模型總是遵守 3NF 模式。
標(biāo)準(zhǔn)的數(shù)據(jù)建模,本身并不是為了商業(yè)智能的工作負(fù)載而設(shè)計(jì)的。太多的表會(huì)導(dǎo)致過(guò)多的關(guān)聯(lián),而表關(guān)聯(lián)會(huì)導(dǎo)致性能下降,在數(shù)據(jù)分析中我們要盡力去避免這種情形發(fā)生。數(shù)據(jù)建模過(guò)程中,通過(guò)反規(guī)范化把多個(gè)相關(guān)表合并成一個(gè)表,例如前面例子里的多個(gè)表被預(yù)合并成一個(gè) geography 表。
那么為何部分人認(rèn)為維度建模已死?
一般人都認(rèn)可數(shù)據(jù)建模的方式,而把維度建模當(dāng)成特殊處理方式,它們都是有價(jià)值的。那為什么在大數(shù)據(jù)和 Hadoop 的時(shí)代,部分人會(huì)認(rèn)為維度建模沒用了?
“數(shù)據(jù)倉(cāng)庫(kù)之死”
首先,一些人混淆了維度建模和數(shù)據(jù)倉(cāng)庫(kù)。他們認(rèn)為數(shù)據(jù)倉(cāng)庫(kù)已死,于是得出結(jié)論:維度建模也可以被丟進(jìn)歷史的垃圾箱。這種論點(diǎn)在邏輯上是連貫的,但是,數(shù)據(jù)倉(cāng)庫(kù)的概念遠(yuǎn)沒有過(guò)時(shí)。我們總是需要集成的、可靠的數(shù)據(jù)來(lái)產(chǎn)生商業(yè)智能儀表盤(BI Dashboards)。
只讀結(jié)構(gòu)的誤解
第二個(gè)常聽見的爭(zhēng)論,比如“我們遵循只讀方式的結(jié)構(gòu)(Schema),所以不需要對(duì)數(shù)據(jù)再進(jìn)行建模了”。依我看來(lái),這是數(shù)據(jù)分析過(guò)程中最大的誤解之一。我同意起初僅轉(zhuǎn)儲(chǔ)原始數(shù)據(jù),這時(shí)不過(guò)多考慮結(jié)構(gòu)是有意義的。但是,這不應(yīng)該成為不對(duì)數(shù)據(jù)進(jìn)行建模的借口。只讀方式的結(jié)構(gòu)只是降低了下游系統(tǒng)的能力和責(zé)任,一些人不得不咬牙去定義數(shù)據(jù)類型。訪問無(wú)模式數(shù)據(jù)轉(zhuǎn)儲(chǔ)的每一個(gè)進(jìn)程都需要自己弄清楚發(fā)生了什么,而這完全是多余的。通過(guò)定義數(shù)據(jù)類型和正確的結(jié)構(gòu),可以很容易地避免這些工作。
再談反規(guī)范化和物理模型
是否那些宣傳維度建模的觀點(diǎn)實(shí)際上已過(guò)時(shí)了?的確有些觀點(diǎn)比上面列出的兩條更好,要理解它們需要對(duì)物理建模和 Hadoop 的工作方式有一些了解。
前面簡(jiǎn)單提到采用維度建模的原因之一,和數(shù)據(jù)的物理存儲(chǔ)方式有關(guān)。標(biāo)準(zhǔn)數(shù)據(jù)建模中每個(gè)真實(shí)世界里的實(shí)體,有一個(gè)自己的表。我們這樣做,是為了避免數(shù)據(jù)冗余和質(zhì)量問題在數(shù)據(jù)中蔓延。越多的表,就需要越多的關(guān)聯(lián),這是標(biāo)準(zhǔn)建模的缺點(diǎn)。表關(guān)聯(lián)的代價(jià)是昂貴的,特別是關(guān)聯(lián)數(shù)據(jù)集中關(guān)聯(lián)大量記錄的時(shí)候尤其突出。當(dāng)我們考慮維度建模時(shí),會(huì)把多個(gè)表合并起來(lái),這就是所謂的預(yù)關(guān)聯(lián)或者說(shuō)數(shù)據(jù)反規(guī)范化。最后的結(jié)果是,得到更少的表、更少的關(guān)聯(lián)、更低的延遲和更好的查詢性能。
可參與領(lǐng)英上相關(guān)的討論。
徹底反規(guī)范化
為什么不把反規(guī)范化做到徹底?去掉所有的表關(guān)聯(lián)只保留一張表?的確,這樣做可以不需要對(duì)任何表進(jìn)行關(guān)聯(lián),但是可以想象到,它會(huì)帶來(lái)一些負(fù)面影響。首先,它需要更多的存儲(chǔ),因?yàn)橐鎯?chǔ)大量的冗余數(shù)據(jù)。隨著數(shù)據(jù)分析的列式存儲(chǔ)格式的出現(xiàn),這一點(diǎn)現(xiàn)在不那么令人擔(dān)憂了。反規(guī)范化最大的問題是,每次屬性值發(fā)生變化,就不得不在很多地方進(jìn)行更新,可能是幾千甚至幾百萬(wàn)次更新。一個(gè)解決辦法是在晚上對(duì)模型進(jìn)行全量重載,通常這比增量更新要更快、更容易。列式數(shù)據(jù)庫(kù)通常采用這種方法,首先將要做的更新存儲(chǔ)在內(nèi)存中,然后異步地寫入磁盤。
分布式關(guān)系型數(shù)據(jù)庫(kù)(MPP)上的數(shù)據(jù)分布
在 Hadoop,例如 Hive、SparkSQL 上建立維度模型,要很好地理解一個(gè)技術(shù)上的核心特征,就是它和分布式關(guān)系型數(shù)據(jù)庫(kù)(MPP)上的建立方式是不一樣的。在 MPP 中的節(jié)點(diǎn)上分布數(shù)據(jù),可以控制每條數(shù)據(jù)記錄的位置。基于分區(qū)策略,例如 Hash、List、Range 等,可以在同一個(gè)節(jié)點(diǎn)上跨表同定位(co-located)各個(gè)記錄的鍵值。由于數(shù)據(jù)的局部性得到保證,關(guān)聯(lián)速度會(huì)非??欤?yàn)椴恍枰诰W(wǎng)絡(luò)上發(fā)送任何數(shù)據(jù)。參考下面圖示的例子,在 ORDER 和 ORDER_ITEM 表中有相同 ORDER_ID 的記錄存儲(chǔ)在同一節(jié)點(diǎn)上:
ORDER 和 ORDER_ITEM 表中 ORDER_ID 對(duì)應(yīng)的鍵值,在相同的節(jié)點(diǎn)做到同定位。
Hadoop上的數(shù)據(jù)分布
數(shù)據(jù)分布在基于 Hadoop 的系統(tǒng)中是非常不同的,我們將數(shù)據(jù)分割成大型的塊(chunks),并在 Hadoop 分布式文件系統(tǒng)(HDFS)的各個(gè)節(jié)點(diǎn)進(jìn)行分發(fā)和復(fù)制。這種數(shù)據(jù)分發(fā)策略不能保證數(shù)據(jù)的一致性。參考下面圖示的例子,記錄 ORDER_ID 的鍵被存儲(chǔ)在不同的節(jié)點(diǎn):
為了關(guān)聯(lián)它們,需要在網(wǎng)絡(luò)上發(fā)送數(shù)據(jù),這樣做會(huì)影響性能。
處理這個(gè)問題的一個(gè)策略,是在集群的所有節(jié)點(diǎn)上復(fù)制要關(guān)聯(lián)的表,該策略被稱為廣播式關(guān)聯(lián)(broadcast join)。如果對(duì) MPP 使用相同的策略,可以想象,只能用在較小的 lookup 或維度表中。
那么當(dāng)關(guān)聯(lián)一個(gè)大的事實(shí)表和一個(gè)大的維度表,比如客戶或產(chǎn)品,甚至關(guān)聯(lián)兩個(gè)大型事實(shí)表時(shí),我們?cè)撛趺崔k?
Hadoop上的維度建模
為了解決性能問題,可以利用反規(guī)范化將大的維度表放進(jìn)事實(shí)表,以保證數(shù)據(jù)是同定位的(co-located),而對(duì)較小的維度表可以在所有節(jié)點(diǎn)上廣播(broadcast)。
關(guān)聯(lián)兩個(gè)大型事實(shí)表時(shí),可以把低粒度的表嵌套到更高粒度的表中,例如把 ORDER_ITEM 表嵌套到 ORDER 表中。高級(jí)的查詢引擎,比如 Impala 或 Drill 可以讓數(shù)據(jù)扁平化(flatten out):
嵌套數(shù)據(jù)的策略很有用,類似于 Kimball 概念中用橋接表來(lái)表示維度模型中的 M:N 關(guān)系。
Hadoop和緩慢變化維
Hadoop 文件系統(tǒng)中的存儲(chǔ)是不可變的,換句話說(shuō),只能插入和追加記錄,不能修改數(shù)據(jù)。如果你熟悉的是關(guān)系型數(shù)據(jù)倉(cāng)庫(kù),這看起來(lái)可能有點(diǎn)奇怪。但是從內(nèi)部機(jī)制看,數(shù)據(jù)庫(kù)是以類似的機(jī)制工作,在一個(gè)進(jìn)程異步地更新數(shù)據(jù)文件中的數(shù)據(jù)之前,將所有變更保存在一個(gè)不可變的預(yù)寫式日志(WAL- write-ahead log,Oracle中稱為redo log)中。
不可變性(immutability)對(duì)維度模型有什么影響?你也許還記得維度建模課程中漸變維的概念(Slowly Changing Dimensions - SCDS)。SCDS 有選擇地保存屬性值變更的歷史,于是可以在某個(gè)時(shí)間點(diǎn)上對(duì)屬性值進(jìn)行度量。但這不是默認(rèn)的處理方式,默認(rèn)情況下會(huì)用最新的值來(lái)更新維度表。那么在 Hadoop 上如何選擇呢?記住!我們不能更新數(shù)據(jù)。我們可以簡(jiǎn)單地為 SCD 選擇默認(rèn)方式并對(duì)每一個(gè)變化進(jìn)行審核(audit)。如果想運(yùn)行基于當(dāng)前值的報(bào)表,可以在 SCD 之上創(chuàng)建一個(gè)視圖,讓它僅僅檢索到最新值,利用 Windows 函數(shù)可以很容易做到這一點(diǎn)?;蛘?,可以運(yùn)行一個(gè)所謂合并(Compaction)的服務(wù),用最新的值物理地創(chuàng)建維度表的一個(gè)單獨(dú)版本。
Hadoop的存儲(chǔ)演化
Hadoop 平臺(tái)的供應(yīng)商并沒有忽視這些 Hadoop 的限制,例如 Hive 就提供了滿足 ACID 的事務(wù)和可更新的表。根據(jù)大量的主要公開問題以及個(gè)人經(jīng)驗(yàn),這個(gè)特性還沒有完善到可以部署生產(chǎn)環(huán)境。Cloudera 采取了另外一個(gè)手段,利用 Kudu 建立了一個(gè)新的可變更存儲(chǔ)格式,它并沒有基于 HDFS,而是基于本地 OS 操作系統(tǒng)。它完全擺脫了 Hadoop 的限制,類似于列式 MPP 的傳統(tǒng)存儲(chǔ)層。通常來(lái)說(shuō),在 Impala + Kudu 這樣一個(gè) MPP 上運(yùn)行 BI 和 Dashboard 的任何使用場(chǎng)景,會(huì)比 Hadoop 更好。不得不說(shuō),當(dāng)它涉及到彈性、并發(fā)性和擴(kuò)展性時(shí),有自己的局限。當(dāng)遇到這些限制時(shí),Hadoop 和它的近親 Spark 是解決 BI 工作負(fù)載的好選擇。
判決:維度模型和星型模式過(guò)時(shí)了嗎?
我們都知道,Ralph Kimball 已經(jīng)退休了,但他設(shè)計(jì)原則的思想和觀念仍然是有效的,也將會(huì)繼續(xù)存在。即使我們不得不讓它們適應(yīng)新的技術(shù)和存儲(chǔ)類型,它們?nèi)匀荒軌驇?lái)巨大的價(jià)值。
補(bǔ)充閱讀
Tom Breur: The Past and Future of Dimensional Modeling
Edosa Odaro: 5 Radical Tips for Speedy Big Data Integration - The Anti Data Warehouse Pattern
感謝蔡芳芳對(duì)本文的審校。