天天看點

Apache Kylin權威指南3.1 為什麼要增量建構

第3章

增量?建構

第2章介紹了如何建構cube并利用其完成線上多元分析的查詢。每次cube的建構都會從hive中批量讀取資料,而對于大多數業務場景來說,hive中的資料處于不斷增長的狀态。為了支援cube中的資料能夠不斷地得到更新,且無需重複地為已經處理過的曆史資料建構cube,是以對于cube引入了增量建構的功能。

我們将cube劃分為多個segment,每個segment用起始時間和結束時間來标志。segment代表一段時間内源資料的預計算結果。在大部分情況下(例外情況見第4章“流式建構”),一個segment的起始時間等于它之前那個segment的結束時間,同理,它的結束時間等于它後面那個segment的起始時間。同一個cube下不同的segment除了背後的源資料不同之外,其他如結構定義、建構過程、優化方法、存儲方式等都完全相同。

本章将首先介紹如何設計并建立能夠增量建構的cube,然後介紹實際測試或生産環境中觸發增量建構的方法,最後将會介紹如何處理由于增量建構而導緻的segment碎片,以保持kylin的查詢性能。

<b></b>

<b>3.1 為什麼要增量建構</b>

全量建構可以看作增量建構的一種特例:在全量建構中,cube中隻存在唯一的一個segment,該segment沒有分割時間的概念,是以也就沒有起始時間和結束時間。全量建構和增量建構各有其适用的場景,使用者可以根據自己的業務場景靈活地進行切換。全量建構和增量建構的詳細對比如表3-1所示。

表3-1 全量建構和增量建構的對比

全量建構 增量建構

每次更新時都需要更新整個資料集 每次隻對需要更新的時間範圍進行更新,是以離線計算量相對較小

查詢時不需要合并不同segment的結果 查詢時需要合并不同segment的結果,是以查詢性能會受到影響

不需要後續的segment合并 累計一定量的segment之後,需要進行合并

适合小資料量或全表更新的cube 适合大資料量的cube

對于全量建構來說,每當需要更新cube資料的時候,它不會區分曆史資料和新加入的資料,也就是說,在建構的時候會導入并處理所有的原始資料。而增量建構隻會導入新segment指定的時間區間内的原始資料,并隻對這部分原始資料進行預計算。為了驗證這個差別,可以到kylin的monitor頁面觀察建構的第二步——建立hive中間表(create intermediate flat hive table),單擊紙張形的log按鈕即可觀察該步驟的參數:

insert overwrite table

kylin_intermediate_test_kylin_cube_without_slr_left_join_desc_20120601000000_20130101000000 select

test_kylin_fact.cal_dt

,test_kylin_fact.leaf_categ_id

,test_kylin_fact.lstg_site_id

,test_category_groupings.meta_categ_name

,test_category_groupings.categ_lvl2_name

,test_category_groupings.categ_lvl3_name

,test_kylin_fact.lstg_format_name

,test_kylin_fact.slr_segment_cd

,test_kylin_fact.price

,test_kylin_fact.item_count

,test_kylin_fact.seller_id

,test_sites.site_name

from default.test_kylin_fact as test_kylin_fact

left join edw.test_cal_dt as test_cal_dt

on test_kylin_fact.cal_dt = test_cal_dt.cal_dt

left join default.test_category_groupings as test_category_groupings

on test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id and test_kylin_fact.lstg_site_id = test_category_groupings.site_id

left join edw.test_sites as test_sites

on test_kylin_fact.lstg_site_id = test_sites.site_id

left join edw.test_seller_type_dim as test_seller_type_dim

on test_kylin_fact.slr_segment_cd = test_seller_type_dim.seller_type_cd

where (test_kylin_fact.cal_dt &gt;= '2012-06-01' and test_kylin_fact.cal_dt &lt; '2013-01-01')

 distribute by rand();

該建構任務對應于名為test_kylin_cube_without_slr_left_join_empty的cube建構,其seg-ment所包含的時間段為從2012-06-01(包含)到2013-01-01(不包含),可以看到在導入資料的hive指令中帶入了包含這兩個日期的過濾條件,以此保證後續建構的輸入僅包含2012-06-01到2013-01-01這段時間内的資料。這樣的過濾能夠減少增量建構在後續的預計算中所需要處理的資料規模,有利于減少叢集的計算量,加速segment建構的時間。

其次,增量建構的cube和全量建構的cube在查詢時也有不同。對于增量建構的cube,由于不同時間的資料分布在不同的segment之中,是以為了獲得完整的資料,查詢引擎需要向存儲引擎請求讀取各個segment的資料。當然,查詢引擎會根據查詢中的條件自動跳過不感興趣的segment。對于全量建構的cube,查詢引擎隻需要向存儲引擎通路單個segment所對應的資料,從存儲層傳回的資料無需進行segment之間的聚合,但是這也并非意味着查詢全量建構的cube不需要查詢引擎做任何額外的聚合,為了加強性能,單個segment的資料也有可能被分片存儲到引擎的多個分區上(參考第6章),進而導緻查詢引擎可能仍然需要對單個segment不同分區的資料做進一步的聚合。當然,整體來說,增量建構的cube上的查詢會比全量建構的做更多的運作時聚合,而這些運作時聚合都發生在單點的查詢引擎之上,是以通常來說增量建構的cube上的查詢會比全量建構的cube上的查詢要慢一些。

可以看到,日積月累,增量建構的cube中的segment越來越多,根據上一段的分析可以猜測到該cube的查詢性能也會越來越慢,因為需要在單點的查詢引擎中完成越來越多的運作時聚合。為了保持查詢性能,cube的管理者需要定期地将某些segment合并在一起,或者讓cube根據segment保留政策自動地淘汰那些不會再被查詢到的陳舊segment。關于這部分的詳細内容會在3.4.1節中展開詳細讨論。

最後,我們可以得到這樣的結論:對于小資料量的cube,或者經常需要全表更新的cube,使用全量建構需要更少的運維精力,以少量的重複計算降低生産環境中的維護複雜度。而對于大資料量的cube,例如,對于一個包含兩年曆史資料的cube,如果需要每天更新,那麼每天為了新資料而去重複計算過去兩年的資料就會變得非常浪費,在這種情況下需要考慮使用增量建構。