天天看點

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

橫看成嶺側成峰,

遠近高低各不同。

不識廬山真面目,

隻緣身在此山中。

不同的視角我們所看到的物體是不一樣的,

<a href="http://t.m.china.com.cn/convert/c_ovwl9w.html">http://t.m.china.com.cn/convert/c_ovwl9w.html</a>

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

圖為墨西哥城放射狀的街區廣場。

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

圖為西班牙迷宮般的果樹漩渦。

地心說和日心說也是視角不同所呈現的。

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐
每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

實際上資料也有這樣,我們每天産生海量的資料,有各種屬性,以每個屬性為視角(分組、歸類、聚合),看到的是對應屬性為中心的資料。

對應的業務場景也非常多,例如:

1、物聯網,

每個傳感器有很多屬性:id,地理位置,傳感器歸屬,各類名額等。

以傳感器的角度進行觀察,觀察某個傳感器id在流金歲月中的值。

以歸屬角度(例如歸屬于公安、城管、某家公司、。。。)進行觀察,

以地理位置為視角進行觀察,。。。。

2、車聯網、站長網。。。。

按車輛、按客戶、按通路者。。。多重視角進行觀察

觀察在資料庫中可以觸發兩種行為,一種是實時計算的行為,另一種是資料規整的行為。

資料規整指将資料按視角重新歸類存放。(例如在雲端彙聚了各個網站的被通路記錄,站長隻關注他自己的網站的被通路記錄,當需要向站長提供資料時,可以按網站進行資料規整)。

那麼如何在雲端實作實時分析、準實時資料歸類的需求呢?

hybriddb for postgresql是阿裡雲的一款分析型mpp資料庫産品(基于greenplum開源版本而來,新增了插件功能、雲端特性以及核心代碼優化),提供了水準擴充的能力以及強大的分析sql相容性,同時與雲端海量存儲oss進行了深度整合,可以并行讀寫oss,将oss作為資料存儲來使用。

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

海量資料源,寫入oss,通過hybriddb for postgresql的oss_ext插件,實時分析寫入的資料。

oss帶寬名額:目前每個計算節點每個會話約30mb/s的讀寫速率。

對于列式存儲格式,數值類型。1億記錄約381mb,壓縮比5:1的話,約76.3mb。

按行換算的性能名額:2048個計算節點,讀寫吞吐約 805億行/s。每天處理6900萬億行(當然,按多列進出打個折扣,萬億級别也是沒有問題的)。

每天萬億+級 實時分析、資料規整 - 阿裡雲HybridDB for PostgreSQL最佳實踐

實時資料規整的目的是按視角将資料規整,資料進入oss時,是打亂的。由hybriddb for postgresql對接重分布分組規整後,再寫出到oss,形成規整的資料。

為什麼需要重分布?

前面談到了視角問題,我們可能有多重視角來觀察資料,而在資料庫中隻能選擇一種固定的分布鍵,當視角與之不同時,就需要重分布。

準實時導出的優化:

對于一個視角,可能有少量或多種屬性,例如使用者實際,假設有100萬個使用者,如果每個計算節點分别導出100萬使用者,每個使用者對應到oss的一個規整檔案,那麼由于檔案數過多,導出會較慢。

那麼可以對使用者重分布,例如1000個節點,每個節點配置設定到1000個使用者的資料,這樣的話,并行寫出到oss時,一下子就降低到了每個節點寫1000個檔案的規模。

如何強制重分布呢?後面講到。

hybriddb for postgresql與oss對接的詳細文檔請參考:

<a href="https://help.aliyun.com/document_detail/35457.html">https://help.aliyun.com/document_detail/35457.html</a>

簡略步驟如下:

1、建立oss使用者

2、建立oss bucket,例如每個小時一個bucket

3、寫入資料(最好寫入小檔案,數量為hybriddb for postgresql的倍數)

4、在hybriddb for postgresql中建立oss外部表,例如每個小時一個

5、直接讀取oss外表進行分析

按不同的視覺次元,進行分組,每個視覺屬性規整到一個oss檔案。也就是說一個oss檔案不能存在多個對象。

比如需要按視角分組,按時間排序輸出。

以上sql,資料庫可能不會按視角字段重分布,而是使用兩階段送出的方式。例如

強制按指定鍵重分布

按強制重分布, 改寫sql

使用視窗查詢,将資料強制重分布,然後再進行計算節點的原地聚合。

greenplum的自定義聚合與單節點聚合不同,一種為單階段模式,另一種為兩階段聚合模式。

單階段模式,将資料收到master後進行聚合。流水:

初始值initcond,master過程函數sfunc,master final函數finalfunc。

兩階段模式先在資料節點并行執行,然後在master執行第二階段。流水:

初始值initcond,資料節點過程函數sfunc(資料節點并行執行),master聚合函數prefunc,master final函數finalfunc。

sfunc操作流水如下

1、每個節點調用sfunc聚合,輸入參數為(input_type資料 , 臨時結果stype),輸出為stype。處理第一條記錄時,臨時結果stype為 null 或 初始值initcond。

兩階段聚合優化方法如下

在節點調用sfunc聚合,輸入參數為(input_type資料 , 臨時結果stype),輸出為stype

segment第一階段收集結果傳輸到master調用prefunc,輸入(stype , stype),得到的結果為stype

最後再将stype轉換為聚合的輸出類型即可(可選使用finalfunc)。

hll_union_agg 優化例子

hll_add_agg 優化例子

但是請注意,由于在segment節點sfunc執行完沒有斷點接口,是以我們無法在segment節點直接将一階段聚合的資料寫入到oss。(除非改gpdb代碼,加入一個斷點接口。)

怎麼辦呢?

通過udf函數來實作,并要求它在每個資料節點單獨執行。

雖然這是一種方法,但是這種方式依舊不是最高效的,因為還有一次聚合的過程。

更高效率的方法是首先對資料重分布和排序,同時在導出到檔案時自動根據上下文的value變化,切換檔案,根據新的value命名并寫入新檔案。

這部分工作需要修改資料庫的導出代碼來實作。

實作了在導出到檔案時自動根據上下文的value變化,切換檔案,根據新的value命名并寫入新檔案這部分工作後,規整資料變得異常簡單。

1、非規整外部表(來源表)

例子

同樣需要使用這種方法進行強制重分布

按uid規整,按crt_time排序

2、建立規整後oss外部表

3、将資料寫入規整後oss外部表

使用hybriddb for postgresql,同時實作了實時分析,準實時資料規整兩個需求。

oss作為海量資料入口,hdb作為oss的計算引擎,實作海量資料實時分析。

同時hdb作為資料規整引擎,被規整的資料不需要在資料庫本地落地,直接從oss到oss,隻是用到了hdb的規整能力。

性能可以通過擴充hdb的計算節點線性擴充:

<a href="https://www.aliyun.com/product/gpdb">阿裡雲hybriddb for postgresql</a>

<a href="https://help.aliyun.com/document_detail/35457.html">阿裡雲hybriddb for postgresql oss存儲用法</a>

<a href="https://github.com/digoal/blog/blob/master/201707/20170725_01.md">《greenplum 性能評估公式 - 阿裡雲hybriddb for postgresql最佳實踐》</a>

<a href="https://github.com/digoal/blog/blob/master/201608/20160825_02.md">《greenplum 最佳實踐 - 估值插件hll的使用(以及hll分式聚合函數優化)》</a>

<a href="https://github.com/digoal/blog/blob/master/201305/20130502_01.md">《postgres-xc customized aggregate introduction》</a>

<a href="https://github.com/digoal/blog/blob/master/201212/20121218_02.md">《postgresql aggregate function customize》</a>