多學(xué)點(diǎn)容易被忽略的數(shù)據(jù)建模知識(shí)
學(xué)點(diǎn)容易被忽略的建模知識(shí)
并不是說(shuō),時(shí)代進(jìn)步了,技術(shù)升級(jí)了,歷史的思考就不再被重視了,恰恰相反,越是頂尖的建模師,越應(yīng)該去看最基礎(chǔ)的理論。就像圍棋一樣,頂尖高手不是靠天馬行空的創(chuàng)意贏得比賽,而是每一步最踏實(shí)的落子。?
-- 讀書筆記《數(shù)據(jù)倉(cāng)庫(kù)生命周期工具箱》。
|0x00 維度建模再重讀
維度方法并不是一個(gè)人發(fā)明創(chuàng)造的,在數(shù)據(jù)庫(kù)設(shè)計(jì)中,它具有不可抗拒的魅力,當(dāng)設(shè)計(jì)人員將【可理解性】和【性能】作為最高目標(biāo)時(shí),維度方法總是首選。
維度建模將客觀世界劃分為度量和上下文,度量是由公司的業(yè)務(wù)過(guò)程和支持它們的業(yè)務(wù)源系統(tǒng)捕捉的,常常以數(shù)值的形式出現(xiàn),我們將它們稱作“事實(shí)”。事實(shí)由大量文本形式的上下文包圍著,這些文本形式的上下文只有當(dāng)事實(shí)被記錄時(shí)才為真。這種上下文被直觀地分割成了多個(gè)獨(dú)立的邏輯塊,我們將其稱作“維”。維度描述了度量上下文的5W(who、what、when、where、why)信息,以及這些上下文是如何作用的。
關(guān)系數(shù)據(jù)庫(kù)平臺(tái)中存儲(chǔ)的維度模型一般都被稱作是星型模式,存儲(chǔ)在OLAP結(jié)構(gòu)中的維度模型被稱為多維數(shù)據(jù)集,OLAP多維數(shù)據(jù)集都可以由維度星型模式生成。
業(yè)界有時(shí)將符合第三范式的模型稱作ER模型,ER是實(shí)體-關(guān)系的首字母縮寫,通過(guò)方框和連線來(lái)描述數(shù)據(jù)庫(kù)表之間的聯(lián)系,第三范式模型和維度模型都可以用ER圖的形式來(lái)描述,二者之間的主要區(qū)別是規(guī)范化程度有所不同,正是因?yàn)榈谌妒侥P秃途S度模型都能夠用E-R圖來(lái)描述,我們才盡量避免將符合第三范式的模型稱作E-R模型,而是將其稱作規(guī)范化模型來(lái)防止混淆。
可解釋性是維度模型得以廣泛應(yīng)用的一個(gè)主要原因,建模過(guò)程中要“讓所有的事項(xiàng)盡可能簡(jiǎn)單,但又不能簡(jiǎn)單得過(guò)了頭”。業(yè)務(wù)分類可以幫助用戶查詢模型,因?yàn)槿绻硞€(gè)分類和具體的分析操作并不相關(guān),那么整個(gè)維度的內(nèi)容都可以被跳過(guò)。但如果業(yè)務(wù)過(guò)程過(guò)度簡(jiǎn)化,那么模型就會(huì)丟失大量有價(jià)值的信息,而這些信息對(duì)于模型的性能好壞和人們理解業(yè)務(wù)過(guò)程往往都是非常重要的。
查詢性能是維度建模的第二個(gè)主要驅(qū)動(dòng)因素,反規(guī)范化維度層次結(jié)構(gòu)和解碼查詢都對(duì)查詢性能有十分重要的影響。
維度模型的第三個(gè)優(yōu)點(diǎn),每個(gè)維都是一個(gè)等效的事實(shí)表入口點(diǎn),這種對(duì)稱性使維度模型能夠承受查詢模式中的意外變化。在即席攻擊中,來(lái)自各個(gè)角落的查詢像暴風(fēng)雪一般涌來(lái),系統(tǒng)無(wú)法預(yù)知它們的查詢模式,不過(guò),維度模型的對(duì)稱結(jié)構(gòu)能夠高效地處理所有查詢?nèi)蝿?wù)。用技術(shù)術(shù)語(yǔ)來(lái)說(shuō),意味著星型聯(lián)接數(shù)據(jù)庫(kù)的查詢優(yōu)化是簡(jiǎn)單、可預(yù)測(cè)和可控制的。
維度模型進(jìn)行擴(kuò)展也是比較容易的,可以容納那些事先未預(yù)料到的新數(shù)據(jù),通過(guò)新增字段就可以進(jìn)行相應(yīng)的該表,而且一般不需要重載數(shù)據(jù)。
綜上所述,按照一定的開發(fā)規(guī)范,寫的又快、讀起來(lái)簡(jiǎn)潔、擴(kuò)展方便、性能還不差,是我們數(shù)倉(cāng)的目標(biāo),維度建模就是數(shù)據(jù)界的“谷歌代碼規(guī)范”。
|0x01 事實(shí)表
事實(shí)表存儲(chǔ)了從機(jī)構(gòu)業(yè)務(wù)活動(dòng)或者事件中提煉出來(lái)的性能度量,“事實(shí)”其實(shí)就是指每種性能度量。一般來(lái)說(shuō),我們不會(huì)預(yù)先知道某個(gè)事實(shí)的價(jià)值,因?yàn)槭聦?shí)也是變化的,對(duì)事實(shí)價(jià)值的評(píng)估出現(xiàn)在度量時(shí)間發(fā)生的時(shí)候,如收到訂單、運(yùn)送訂購(gòu)貨物或者記錄服務(wù)問(wèn)題等事件。可以想象自己正在裝貨點(diǎn)觀察運(yùn)輸?shù)倪^(guò)程,在產(chǎn)品被搬放到即將出發(fā)的貨車上的過(guò)程中,每次都會(huì)產(chǎn)生一些事實(shí)(性能度量),例如運(yùn)輸量,幾乎每一個(gè)事實(shí)都是數(shù)值型,大多數(shù)的事實(shí)是具備可加性的,這非常重要。
事實(shí)表在設(shè)計(jì)時(shí),每個(gè)外鍵都必須和對(duì)應(yīng)維度表的唯一主鍵相匹配,也就是說(shuō),事實(shí)表的外鍵不應(yīng)當(dāng)為空,因?yàn)槿绻麨榭眨?span style="color: rgb(217, 33, 66);">違背了參照完整性。
事實(shí)表應(yīng)當(dāng)包含從業(yè)務(wù)過(guò)程中捕捉的最底層的、最細(xì)節(jié)的原子粒度,這樣的數(shù)據(jù)會(huì)具有很強(qiáng)的靈活性和彈性,以盡可能地支持精確的查詢請(qǐng)求。設(shè)計(jì)師Mies van der Rohe信奉這樣的說(shuō)法:“上帝是偏愛細(xì)節(jié)的。”事實(shí)表如果具有最細(xì)節(jié)的數(shù)據(jù),那么就可能使模型具有最大的靈活性和可擴(kuò)展性。
事實(shí)表通常是快速增長(zhǎng)、不斷變化的,因?yàn)樗偸谴鎯?chǔ)最細(xì)的細(xì)節(jié),而事實(shí)表的復(fù)雜程度,可以決定我們下游數(shù)倉(cāng)的實(shí)時(shí)程度。當(dāng)你的業(yè)務(wù)邏輯不太復(fù)雜時(shí),數(shù)倉(cāng)的設(shè)計(jì)便可以脫離離線的思維,通過(guò)實(shí)時(shí)的方式進(jìn)行計(jì)算,或者通過(guò)OLAP引擎,直接面向數(shù)據(jù)庫(kù)統(tǒng)計(jì)。但如果你的業(yè)務(wù)很復(fù)雜,比如訂單金額拆分子訂單,遇到除不盡的情況時(shí),或者是遞歸層次遇到圖關(guān)系情況時(shí),傳統(tǒng)離線數(shù)倉(cāng)還是很適合處理這一類的情況。
|0x02 維度表
事實(shí)表僅由鍵和數(shù)值型度量所組成,因此它們具有健壯性和完整性的特點(diǎn),但與事實(shí)表不同,維度表不具有健壯性和完整性,它們當(dāng)中充滿了“大而笨重”的描述性字段。
因此,維度模型的優(yōu)點(diǎn)在于所有的屬性成為過(guò)濾條件或者標(biāo)記的時(shí)候都是等價(jià)的,它具備了以下的特點(diǎn):
是冗長(zhǎng)的(名稱由完整的詞匯組成) 是描述性的 是完整的(沒有遺漏值) 是離散取值的(維度表中的每一行僅取一個(gè)值) 質(zhì)量是有保證的(沒有錯(cuò)誤拼寫等)
這里有個(gè)小技巧,維度屬性列中的空值常常會(huì)使業(yè)務(wù)用戶感到困惑,并且會(huì)使SQL查詢語(yǔ)句的性能受到影響,因此我們一般推薦使用描述性的字符串來(lái)代替空值,如“未知”。
維度表幾乎必然會(huì)用于表示層次關(guān)系,在一個(gè)單獨(dú)的維里面,解析幾個(gè)多對(duì)一的層次關(guān)系很常見,這也是反規(guī)范化的必然結(jié)果。例如,如果產(chǎn)品可以上卷到品牌,而品牌可以上卷到類別,就可以用一個(gè)單獨(dú)的產(chǎn)品維度來(lái)表示該層次的關(guān)系,該表中有和品牌及類別描述相對(duì)應(yīng)的屬性。部分人會(huì)認(rèn)為應(yīng)該將品牌和類別分別存儲(chǔ)在單獨(dú)的維中,但這樣做會(huì)干擾可理解性和查詢性能。
規(guī)范化的一致性維度是所有精心設(shè)計(jì)的數(shù)據(jù)倉(cāng)庫(kù)都在追求的目標(biāo),有時(shí)也將其稱為主維度或者公共參照維度。如果兩個(gè)一致性維度是完全相同的,那么它們有相同的鍵、屬性名、屬性定義和域值,不管它們聯(lián)接什么樣的事實(shí)表。例如銷售訂單事實(shí)表所參照的產(chǎn)品維和庫(kù)存量事實(shí)表所聯(lián)接的產(chǎn)品維度是相同的。這種維度表提供了相同的內(nèi)容和解釋,不管相關(guān)的業(yè)務(wù)過(guò)程如何。
上游加個(gè)維度,或者去掉一個(gè)維度,都是業(yè)務(wù)很常見的情況,但如果維度無(wú)法保證一致性,一次業(yè)務(wù)改動(dòng)就足夠讓下游忙活半天了,例如將緩慢變化維放到了事實(shí)表里,這個(gè)維度沒了,下游卻依賴了上千張表,一種“積重難返”的感覺就會(huì)油然而生。你可以為了速度不仔細(xì)考慮維度的變化,但當(dāng)問(wèn)題發(fā)生時(shí),我們就只能被迫的“以災(zāi)難推動(dòng)規(guī)范治理”了。
|0xFF 結(jié)語(yǔ)
本文大部分是從原書中摘抄的段落。之所以要發(fā)出來(lái),是因?yàn)樽罱鼘?duì)于維度模型的理解,有了一些更深層次的感受。
例如,維度模型的第一要義是可解釋性,但事實(shí)上,大多數(shù)的非數(shù)據(jù)從業(yè)人員,都不太理解維度模型的理念,正常的認(rèn)知是,我怎么好用,就怎么設(shè)計(jì),為什么要冗余這么多信息,思考這么多過(guò)程。但對(duì)于數(shù)據(jù)從業(yè)人員而言,按照規(guī)范,就降低了很多未來(lái)挖坑的可能性,就像是Java編碼規(guī)范一樣,壞的代碼總是一直被寫出來(lái),只是為了把業(yè)務(wù)跑起來(lái),但苦了下一代接手的程序員。在工程界,各種規(guī)范、CR都應(yīng)用的很廣泛了,但數(shù)據(jù)領(lǐng)域,似乎還沒有達(dá)成共識(shí)。
所以,讀一些老書,很重要,因?yàn)槔系囊恍﹫?chǎng)景,不會(huì)那么復(fù)雜,便于理解一件事情最原本的初心。
