tp5某个字段相同的数据只取一次_多维分析数据仓库建设建议-面向主题的建模...
數倉使用數據庫構建
數倉的作用簡單來說就是存儲數據和讀取數據。
絕大部分情況下,數據是結構化的,因此存儲數據使用數據庫,使用SQL語言進行數據處理。
多維分析
多維分析是指使用數據的場景,查詢時組合維度屬性和指標,輸出特定組合維度下的指標值。
數倉的基本要求是提供多維分析能力。即對于高度聚合的數據可以快速獲得結果,例如查看過去一年的去重用戶數。
多維分析是從使用者角度看數倉應該提供的能力,而OLAP系統是指具有多維分析能力的系統,相對立的概念是OLTP系統,提供的能力是即時查詢。
例如常見的分析行為有:切片,切塊,旋轉,上卷,下鉆,這些操作在沒有數據倉庫時也能做(數據湖),但是會消耗大量資源且有大量重復勞動,而數倉是提前將這些分析所需數據計算好,在使用時能快速響應。
數據庫不只有構建數倉的功能,其更常用的是為業務提供數據存儲和查詢,前者是OLAP,后者是OLTP。
OLTP是讀寫量少,要求速度快,保證事務,OLAP是讀數據量大,沒有寫操作,不要求實時。
關于分布式和單機數據庫
在OLTP領域,分布式和單機數據庫是兩個非常不同的領域,短期內不可能出現分布式完全替代單機數據庫的情況。因為分布式情況下事件順序無法確認先后,無法保證事務,建立跨機器二級索引困難,強一致性下只能提供單臺機器讀寫性能,這些問題無法克服。
當前分布式數據庫在業務上,只能用于對數據準確性要求不高的業務,或者只提供單機性能但穩定性更高的系統。
在OLAP領域,分布式和單臺數據庫在構建數倉時沒有大區別,只是數據量的不同,即單機數據庫和分布式都可以構建OLAP系統。
當前因為各行業數據量快速增長,目前大量OLAP系統采用分布式環境構建。
底層數據使用星型模型
用于OLTP的數據庫一般使用范式建模,滿足范式時,數據冗余少。
但是實時查詢時使用外鍵進行多次關聯會導致速度變的非常慢,例如用戶瀏覽表和用戶點擊表做關聯時,因為兩張表數據量過大導致關聯查詢速度極慢,也可能導致內存不足。
當然業務數據庫不會發生大表關聯的操作,業務數據庫都是直接取部分數據,最多使用二級索引過濾非主鍵字段。這是因為業務數據庫以快速準確的響應為最高優先級,而數倉對查詢耗時的要求相對低一些。
OLAP則有大量的大表關聯聚合操作,且大表關聯后的數據又會用于和其他表做關聯聚合(嵌套join)。使用單機數據庫時有可能導致內存不足,當下一般使用分布式存儲和處理數據。
用于OLAP的數據庫使用星型模型,即大表提前關聯融合好,產出的表叫寬表或者事實表,與寬表關聯的維表數據量都是極少的。以單張事實表為中心,周圍是幾張小維度表,這是每一個主題的底層數據結構。
星型模型使用空間換時間,提前將事實表和維度表準備好,不進行實時關聯。例如要分析用戶購物轉化主題,則將用戶的瀏覽和實際購買關聯,一般瀏覽數據遠大于購買數據,在事實表中購買數據其實是有大量重復的。
什么是主題建模
主題建模是數倉整體建設中的一個環節,數倉建設主要步驟有:數據提取,數據清洗,主題建模,應用層開發,數據接口這幾個步驟。
每一個主題的底層由一張事實表和多張維度表組成。
事實表中,除了和維表進行關聯的字段外,其余字段為原子指標。
事實表使用維表的屬性進行聚合后,產生結果聚合表。
結果聚合表中,除了聚合的維度外,其余字段為衍生指標,即通過原子指標計算而來的指標。
理論上,一個主題包括一個事實表和多個維度表,以及一個結果聚合表。工程實踐中可能會有多個事實表,但關聯后可以看抽象做一張事實表。工程實踐中出于優先級或者性能考慮,可能會將結果切分為多個結果聚合表。
理論上,主題建模是窮盡所有維度屬性和指標的組合,以及原子指標到衍生指標的計算邏輯,提供任何維度屬性下任意衍生指標的查詢。但是在工程實踐中,是無法窮盡所有組合的,甚至僅計算考慮到的組合也會遠遠大于存儲和計算的承受能力。
工程實踐中,主題建模是對原始數據、原始業務理解的基礎上,將數據歸類為多個主題,將其中重要的原子指標和重要維度屬性進行組合,產出部分維度屬性組合下的衍生指標。
主題建模是對數據的分類,這需要對某個領域甚至某個公司內數據特征有深刻理解。主題建模最大的壁壘也在于此,這部分長期來看無法自動化。清晰的主題規劃往往是數倉設計成敗的關鍵。
主題建模優勢
與主題建模相對的,是按需輸出數據,按照產品的需求出對應指標。當然在產出指標前,會查看之前是否產出過相同或者相關指標,如果有的話,會復用之前的數據。
這種按需出指標的方式相比主題建模而言,優勢是更加靈活,需求不必等待多維分析數倉建立完成即可開始,前期開發周期短。
主題建模是提前將維度和指標的全集定義好,出盡可能多的維度屬性和指標的組合,即全集中的一個子集。
優勢在于簡潔和穩定,與產品需求解耦,不會隨產品需求增加而將數倉變得臃腫,可維護性好,長遠來看性能上也更好。
數據清洗和主題建模關系
這兩者應該在設計時分開。
當原始數據結構復雜時,數據清洗可能無法直接使用SQL進行清洗。并且各個領域下,各個產品的原始數據結構差距很大,一般清洗工作都需要定制化處理,且復用性不高。
這里只描述主題建模的流程。
事實表與主題
事實表是不再需要進行任何清洗操作,只包含維度值和指標的表,一般在數倉分層中為DWD層,特殊情況下也會是DWS層(來自其他主題的結果聚合表)。
主題是無關乎事實表中的維度,而是從指標中抽象出來的,是對事實表所有指標的一個抽象概括。例如事實表是單日單店單品的銷售信息,那么主題代表的是銷售信息。
事實表要盡可能寬,盡可能容納此主題下所有指標,如果有新指標需求,則動態添加指標。當前所有數據庫都支持動態添加字段的操作。
但是事實表太寬可能導致后續計算資源不足,如果需要拆分事實,拆分事實表的過程即拆分子主題,每個子主題盡可能將未來不會組合計算新指標,并且每個子主題都有業務意義。
主題的命名
主題命名建議使用事實表中維度名(主鍵),加上對事實表指標的抽象進行命名,例如事實表是單日單店單品維度的,指標為銷售相關信息,那么主題可以命名為sales_store_goods。
主題的名字應當包含所有信息且簡短,一般情況下,不把日期作為主題名稱的一部分,因為日期往往是一個默認的維度,可以在維護主題元數據的wiki上增加一列事實表的日期粒度。
主題與分層的關系
主題和分層沒有必然聯系,一般主題是從DWD層聚合到DWS層,事實表位于DWD層,結果聚合表位于DWS層。但是有些情況下,在某個主題內,DWS層的表也會作為這個主題下的事實表,用于聚合衍生指標。
數據流向在分層體系中不是單向的,即有可能從DWD到DWS,再到DWD。但是在一個主題內,數據流肯定是單向的,即從事實表到結果聚合表。
某些情況下,事實表的某個指標來源復雜,來自某個DWS表的某個字段。但是從主題的角度來看,主題不關心事實表字段來源,只把攜帶原子指標的表看做底層事實表。例如商品的是否新品是事實表的一個指標,但需要從另一個新品主題的結果聚合表中獲取。
原子指標和衍生指標
事實表中的指標為原子指標,這個定義無特殊作用,只表明此主題下其他指標(衍生指標)都根據這些指標計算而來。
事實表中的指標因為口徑不同,可能導致難以理解,需要在原子指標定義時明確好指標含義,后續聚合形成的指標也會自動保持口徑一致。
不允許對事實表中的原子指標進行修改,只允許增加原子指標。
衍生指標的計算邏輯可能會非常復雜,此時需要考慮拆分結果聚合表。
維度表
維度表包含維度值和維度屬性,其中維度值是和事實表關聯的主鍵,維度屬性是此維度所屬的分類。
維度表是屬于主題的,理論上一個維度表只服務于一個主題,在工程實踐中可以多個主題共用某一個維度表。例如多個主題共用同一張日期維度表。
維度的屬性一般位于維度表中,但有時維度也會轉變為事實表中的指標。例如是否新品即可以做維度,統計新品和非新品的銷量,也可以作為指標,統計對應分類下,新品的總數量。作為指標時需要提前將維度屬性寫入事實表中。
這里使用一種“垂直”的維度表,這種維度表可以讓最終生成的SQL代碼非常簡潔,可用于自動化生成SQL。維度表一共分為四類信息,直接映射為四個字段,即維度表只有四個字段。
日期維度表
必須將日期也作為一張普通的維度表,日期維度表格式與普通維度表格式相同。需要區分運行日期和事實表中日期字段的概念。
實踐中往往只有一個運行日期,但是事實表的日期是一個范圍。事實表主鍵則是運行日期“周圍”的一些日期,因為此維表和事實表做關聯時,事實表中的日期其實是包含一段時間范圍的。
例如運行日期是以天為周期,而每天需要取事實表的當月范圍內數據作為一個“臨時視圖”,此時視圖中的日期不只有運行日期,而是與日期維度表中的維度值相對應的日期值。
維度屬性名稱是這個視圖日期對應的屬性,例如第幾周,是否假期等。而維度屬性值固定為1,代表此日期是維度名稱代表的屬性。
之所以維度屬性值固定為1,是因為維度屬性名稱是不飽和的。一般的維表中,不同維度值對應的維度屬性名稱都大部分情況下是相同的,例如店鋪維表,每個店鋪id都包含N個維度屬性,而日期維度表不同,例如視圖日期是否“在當周時間范圍內”,那些不在當周范圍內的日期一般不需要統計,所以沒有維度屬性為0的情況。
注意不飽和性不是日期維表的特征,其他維表也有可能出現維度屬性不飽和,只是日期維表出現的較多。
舉例,對于某個運行時間dt,不是所有事實表主鍵都有對應值。例如,"視圖日期"維度名稱為dt_view,對于運行時間dt=2020-01-01,有天周月的聚合需求,則dt_view的取值不會小于2019-12-01。
日期維表會有不固定數量的維度名稱,例如,"視圖日期"維度名稱為dt_view,對于運行時間dt=2020-01-01,有天周月的聚合需求,dt_view=2019-12-31可以取值為周、月,因為對運行時間dt而言,2019-12-31這個日期在求周指標和月指標時需要用到,dt_view=2020-01-01可取值為天、周、月,dt=2019-12-01可以取值為月,因為對dt而言,2019-12-01這個日期只有在月指標時需要用到。
結果聚合表
結果聚合表中包含各類維度屬性的組合,以及按照維度聚合、計算后的衍生指標。
理論上,一個主題只生成一張結果聚合表,可以使用不同分區來區分不同維度下的指標。
工程實踐中,不同維度值下數據量存在較大差異,數據量級差距過大的數據存放在一個分區內會導致查詢速度變慢,因此需要將維度屬性作為分區鍵。
只有一個結果表的缺點是無論做什么查詢,都需要增加where條件篩選維度分區,但是這和分為多個結果表的查詢所耗費精力是等價的,因為多表時也需要主題+維度找到對應的數據表。
聚合表的命名規范為dws+主題+運行周期。這里需要注意結果表的主鍵其實已經擴充為維表所有維度之和,但是工程上一般維度總數很大,不適合做表名。
例如單日單店單品的銷售主題,產生的結果聚合表有單月單店大類、單周全店單品等不同維度組合,無法使用聚合后的維度作為表名。
一個主題下只有一個結果表,這能避免表名中描述維度組合,因為只要確定所屬主題的來源事實表,即默認所有維度組合指標都在對應結果聚合表中,從而使找表工作更加便捷。
只有一個結果表的更深層次原因是,所有粒度的表應該都從原始的事實表出,例如事實表為天粒度,一般會認為可以天粒度聚合到周粒度再聚合到月粒度,但實踐中往往會產生部分指標無法從上一層的聚合指標再聚合得到,典型如需要去重統計的指標。
一個實例來解釋以上的內容
以電商行業的銷售主題為例,建立多維分析指標,簡化指標數量和維度數量后,流程如下:
事實表 dwd_sales_store_goods_di
屬于dwd層,主題為單日單店單品-銷售,其中維度(主鍵)為store_id+goods_id+dt,是天級別增量數據(date increase),字段如下
維度表 dim_store 店鋪維表
備注:
一個store_id對應多個店鋪維度名,例如一個store_id對應dim_name=type時,dim_value=0,dim_name=store_level時,dim_value=3。
在此樣例中,認為一個店鋪id對應三個dim_name,但是此數倉建設理論上不強制對應的數量。
建議絕大部分維度表增加dim_name=all選項,這是為了方便出“所有店鋪的某個品類銷量”這類指標。
維度表 dim_goods 商品維表
維度表 dim_dt 日期維表
舉例說明,其中某幾行數據如下
結果聚合表 dws_sales_store_goods_di
屬于dws層,為銷售(sales)主題,其中維度發生改變,從事實表的店鋪+商品+擴展為維表中的所有維度屬性,是天級別增量數據(date increase),盡管其中內容有月度指標,字段如下
SQL:
只使用一個SQL來生成結果聚合表。
代碼自動生成
因為此處SQL格式嚴格規范,可以通過事實表和維度表的元數據自動生成SQL,即SQL語句可以自動生成。
還可以加入自動生成調度任務和DAG的邏輯,使整個主題的產出完全自動化。
向后兼容
兼容性主要體現在三個方面:
原子指標、衍生指標的增長:需要增加結果表的schema,所有數據庫是兼容的,產生結果表的SQL修改其中讀取事實表的查詢,可以向后兼容
維度屬性的增長:在維度表中增加具體的維度屬性即可,不需要其他修改。
維度的增長:產生結果表的SQL增加新的維度表,結果表的schema也進行相應修改。
數據量膨脹
樣例中產生了所有維度和指標的組合,和kylin原理類似,容易導致數據量膨脹。
可以進一步優化SQL解決問題,具體是將其中子查詢進行限制。限制的方式有以下幾種:
對事實表的指標進行限制,有些事實表的指標可能短期內不會使用,可以只提取部分關鍵字段,這樣能減少結果聚合表產生的列數量。未來可以動態添加原子指標。
對維度屬性進行限制,某些維度屬性暫時不需要產出指標,可以在子查詢中進行屏蔽,后續有需要再打開,不需要修改SQL和結果表即可兼容。
對維度表進行限制,某些維度暫時不需要分析,可以在SQL中不進行關聯,后續有需求再增加連接。
總結
ONE SOURCE, ONE SQL, ONE TABLE
一個主題只能有一張來源的事實表,通過一個SQL即生成所有目標維度下的指標,最終只形成一張結果聚合表。
某些情況下提供一個API用于訪問,不過一個API會導致權限系統復雜等問題,此處不考慮。
其他思考
日期也需要制作一張維度表
在生成結果聚合表之前,所訪問的事實表和維度表都不是全量表,是一段時間周期內表的一張視圖,這張視圖包含了此次要參與計算的所有數據內容。
在生成這個中間視圖時,會使用日期字段,這往往會讓開發人員對時間分區字段特殊對待。
其實分區字段在SQL語句中和普通字段沒有區別,將日期字段作為普通維度是可行的。但可以作為維度的是視圖中的日期字段,因為這個日期也需要進行聚合。
所不同的是,因為視圖中的日期是過多的,因此日期維度需要承擔額外的過濾工作,例如視圖中某個日期,有“相對運行日期而言,是否屬于周”這個維度,理論上應該取值0和1,但實際只有在周內的日期才有這個維度。
維度表的兩種形式討論
維度表存在兩種形式,一種如上所述,另一種是常見的“拍平”形態,即維度表主鍵+各個維度值。
這兩者沒有本質區別,只是在生成代碼的簡潔程度不同。
如果采用拍扁形式,則需要使用grouping set來進行聚合,SQL代碼會相對比較復雜。但是扁平方式的可讀性更好,通過schema即可得知維表結構。
公平性問題
在聚合任務中,不同維度組合是公平進行的,但是需求上可能部分維度組合的優先級更高。
解決辦法是對SQL再包一層,SQL改為可動態傳入參數形式,從而將一個SQL切分為多個SQL,將更高優先級的維度組合放在外部SQL的前部。
注意此處如果將所有維度都進行拆分,會造成重復讀取數據量過大,導致資源消耗的極大增加。需要平衡所需切分的維度組合,不能切分過細。
DWS到DWA
某些情況下,主題也可以從DWS層到DWA層,前提是形成視圖的邏輯基本,例如只是從原來取一段連續時間改為取同環比的時間。
如果項目中所需要出的DWA指標近乎包含所有排列組合,那么可以考慮使用這套框架。
業界工具的討論
Kylin使用聚合所有維度的形式,提供了毫秒級響應多維查詢的需求。但是資源消耗巨大,主要是存儲資源。
MPP使用現場計算,將數據導入緩存等方式進行加速。同樣資源消耗巨大,主要是計算資源。
以上產品是兩個極端,如果有開發能力,建議采用中間狀態,即按照多維分析的標準進行設計,在設計完成后,不產出所有維度組合的指標,但可以平滑的進行升級,產出更多指標。
任務深度過深
任務深度過深是難以管理的,主題建模需要在任務深度和任務內部復雜度上做平衡。
主題不能局限于細節,例如五分鐘、一小時、半天、一天、一周、一個月、一年都作為一個主題,會造成任務深度過深。
主題不能太粗糙,例如上述時間粒度都集中在一個主題,會導致有些分鐘粒度的指標在月維度下沒有必要產出。
主題的粗細劃分需要對業務原始數據有深刻理解。
總結
以上是生活随笔為你收集整理的tp5某个字段相同的数据只取一次_多维分析数据仓库建设建议-面向主题的建模...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为手机所有图标变黑_华为官博科普手机状
- 下一篇: 帝豪gl车机系统降级_从拥有帝豪GL开始