天天看點

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

本節書摘來自華章出版社《greenplum企業應用實戰》一書中的第3章,第3.1節,作者 何勇 陳曉峰,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

從本章開始我們結合實際需求,闡述一下日常項目開發中如何結合greenplum的特性進行高效的開發,展現出greenplum在海量資料分析中的優勢。

本章将介紹兩個完整的例子:資料倉庫拉鍊記曆史和網頁浏覽日志分析。在這兩個例子中,會結合greenplum的一些特性加以描述,之後會介紹使用greenplum中要注意的一些特性,以及這些特性對性能的影響。

資料倉庫是一個面向主題的、內建的、相對穩定的、反映曆史變化的資料集合,用于支援管理決策。由于需要反映曆史變化,資料倉庫中的資料通常包含曆史資訊,系統記錄了企業從過去某一時點(如開始應用資料倉庫的時點)到目前的各個階段的資訊,通過這些資訊,可以對企業的發展曆程和未來趨勢做出定量分析和預測。

曆史拉連結清單是一種資料模型,主要是針對資料倉庫設計中表存儲資料的方式而定義的。顧名思義,所謂曆史拉連結清單,就是記錄一個事物從開始一直到目前狀态的所有變化的資訊。拉連結清單可以避免按每一天存儲所有記錄造成的海量存儲問題,同時也是處理緩慢變化資料的一種常見方式。

現假設有如下場景:一個企業擁有5000萬會員資訊,每天有20萬會員資料變更,我們需要在greenplum中記錄會員表的曆史變化以備資料挖掘分析等使用,即每天都要保留一個快照供查詢,反映曆史資料的情況。在此場景中,需要反映5000萬會員的曆史變化,如果保留快照,存儲兩年就需要2×365×5000w條資料存儲空間,資料量為365億,如果存儲更長時間,則無法估計需要的存儲空間。而用拉鍊算法存儲,每日隻向曆史表中添加新增和變化的資料量,每日不過20萬條,存儲4年也隻需要3億存儲空間。

接下來我們将概要講述整個分析實施過程。

在拉連結清單中,每一條資料都有一個生效日期(dw_beg_date)和失效日期(dw_end_date)。假設在一個使用者表中,在2011年12月1日新增了兩個使用者,如表3-1所示,則這兩條記錄的生效時間為當天,由于到2011年12月1日為止,這兩條記錄還沒有被修改過,是以失效時間為無窮大,這裡設定為資料庫中的最大值(3000-12-31)。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

第二天(2011-12-02),使用者10001被删除了,使用者10002的電話号碼被修改成13600000002。為了保留曆史狀态,使用者10001的失效時間被修改為2011-12-02,使用者10002則變成兩條記錄,如表3-2所示。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

第三天(2011-12-03),又新增了使用者10003,則使用者表資料如表3-3所示。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

如果要查詢最新的資料,那麼隻要查詢失效時間為3000-12-31的資料即可,如果要查詢12月1号的曆史資料,則篩選生效時間≤2011-12-01并且失效時間>2011-12-01的資料即可。如果查詢的是12月2号的資料,那麼篩選條件則是生效時間≤2011-12-02 并且失效時間>2011-12-02。讀者可對表3-3的資料進行篩選,以檢驗結果是否正确。

在greenplum中,則可以利用分區表按照dw_end_date儲存時間,這樣在查詢的時候可以利用greenplum的分區裁剪,進而減少io消耗。下面通過圖3-1講解拉連結清單重新整理的步驟,連線代表資料流向,線上的編号就是步驟編号。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

首先介紹每個表的用途。

member_fatdt0:表示member的事實表,其中p30001231儲存的是最新資料,每個分區保留的都是曆史已失效的資料。

member_delta:當天的資料庫變更資料,action字段表示該資料為新增(i)、更新(u)、删除(d)。

member_tmp0:重新整理過程中的臨時表,這個表有兩個分區,分别記錄曆史資料,即當天失效資料,另一個分區記錄的是目前資料。

member_tmp1:同樣是重新整理過程中的臨時表,主要是在交換分區的時候使用。

重新整理過程簡單來說,就是将前一天的全量資料(分區p30001231)與當天的增量資料進行關聯,并對不同的變更類型(action)進行相應的處理,最終生成最新資料,以及當天發生變更的曆史資料。後續資料重新整理實戰中會介紹具體的步驟,下面先從表結構開始介紹。

拉連結清單(member_fatdt0)結構

member_fatdt0使用member_id作為分布鍵,使資料盡量打散在每個機器上(參考3.3節資料分布),通過with(appendonly=true,compresslevel=5)指定該表為壓縮表,可以減少io操作(參考3.4節資料壓縮),将dw_end_date作為分區字段。建表語句如下:

增量表(member_delta)結構

建表語句如下:

臨時表0(member_tmp0)結構

dtype為分區字段,h表示曆史資料,c表示目前資料,建表語句如下:

臨時表1(member_tmp1)結構

表結構與member_tmp1、member_fatdt0一模一樣,建表語句如下:

在這裡為了清晰展示整個邏輯,僅以少量demo資料為例。

(1)增量表資料

12月2号增量資料,新增、删除、更新各有一條記錄,如表3-4所示。

表3-4 12月2号增量資料

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

12月3号增量資料,新增、删除、更新各有一條記錄,如表3-5所示。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

(2)曆史表初始資料

初始資料為12月1号,失效日期為3000年12月31号,如表3-6所示。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

greenplum資料加載主要包括标準sql的insert、copy、外部表、gpload、web external table幾種方式,通過這個例子,将這幾種方式一起來向讀者介紹一下。

insert

這種資料加載方式效率最差,隻适合加載極少量資料。這裡向12月2号會員增量表中插入資料:

copy

copy這種資料加載方式源于postgresql,較sql的 insert方式效率大大提升,但是資料仍然需通過master節點,無法實作并行高效資料加載。這裡向會員曆史表加載12月1号開始的初始資料。

我們将資料以逗号分隔,存放在member_his_init.dat檔案中,内容如下:

copy指令如下,指定分隔符還有資料檔案。

外部表

外部表在2.3.8節中已經簡單介紹過了,首先,啟動gpfdist服務:

其次,建立外部表:

最後,執行資料裝載:

gpload

gpload是對外部表的一層封裝,詳細可參考使用者手冊,這裡直接介紹使用文法,首先,編寫gpload控制檔案member.yml,代碼如下:

其次,執行資料加載:

最後,驗證資料:

可執行外部表

可執行外部表會在6.3.4節中介紹,其中基于作業系統指令讀取資料檔案的方式如下,用法跟普通外部表類似,不過不用啟動gpfdist服務,下面的外部表隻在master上執行:

清空member_delta表并插入資料:

拉連結清單重新整理

step1:對事實表中最新資料(分區p30001231)與member_delta表中的更新、删除資料進行左外連接配接,關聯上則說明該資料已發生過變更,需要将該資料的失效時間更新為當天,并插入到member_tmp0表中的曆史資料分區中,關聯不上則說明沒有發生過變更,需要将該資料插入到member_tmp0表的目前資料分區中。greenplum會根據dtype的資料自動選擇對應的分區。

初始全量資料為2011-12-01号,在12月3号重新整理12月2号增量資料,代碼如下:

step2:将member_delta的新增、更新資料插入到member_tmp0表的目前資料分區中。

step3:将member_fatdt0表中的對應分區(p20121201)與member_tmp0表的曆史資料分區交換。

step4:将member_fatdt0表中對應的目前資料分區(p30001231)與member_tmp0表的目前資料分區交換。

至此,拉連結清單資料重新整理完成,資料驗證如圖3-2所示。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

同樣,更新對應的日期,可以重新整理3号的增量資料。

曆史資料查詢

基于拉連結清單,我們可以回溯到曆史上任意一天的資料狀态。

《Greenplum企業應用實戰》一第3章 Greenplum實戰3.1 曆史拉連結清單

下面通過檢視執行計劃(第5章講詳細介紹執行計劃)來介紹greenplum的分區表的功能。

全表掃描的執行計劃如下:

通過執行計劃可以看出,greenplum掃描了所有的分區。當加入篩選條件dw_end_date='3000-12-31'時,執行計劃如下:

這時,分區裁剪發生了作用,隻掃描了p30001231這個分區。

greenplum在處理大資料量資料導出時常用的方式主要有并行導出(可寫外部表)和非并行導出(copy),copy指令比較簡單,就不細說了。下面我們分别簡單介紹下可寫外部表資料導出方式,通過gpfdist可寫外部表将資料導出至檔案伺服器。

1)建立可寫外部表:

writable關鍵字表示該外部表是可寫外部表;like語句表示建立的外部表的表結構與member_tmp1表結構一樣;location指定gpfdist的機器名跟端口,還有儲存的檔案名;format為導出檔案格式定義。

2)執行資料導出:

跟普通insert語句一樣,隻需要将資料插入外部表即可。

3)驗證生成的檔案:

繼續閱讀