Apache Kylin 深入Cube和查詢優化 提升Cube
近幾年,Apache Kylin作為一個高速的開源分散式大數據查詢引擎正在迅速崛起。它充分發揮Hadoop、Spark、HBase等技術的優勢,通過對超大規模數據集進行預計算,實現秒級甚至亞秒級的查詢響應時間,同時提供標準SQL介面。目前,Apache Kylin已在全球範圍得到了廣泛應用,如百度、美團、今日頭條、eBay等,支撐著單個業務上萬億規模的數據查詢業務。在超高性能的背後,Cube是至關重要的核心。一個優化得當的Cube既能滿足高速查詢的需要,又能節省集群資源。本文將從多個方面入手,介紹如何通過優化Cube提升系統性能。
Cube基本原理
在傳統多維分析就有多維立方體(OLAP Cube)的概念。Apache Kylin在大數據領域對Cube進行了擴展,通過執行 MapReduce/Spark任務構建Cube,對業務所需的維度組合和度量進行預聚合,當查詢到達時直接訪問預計算聚合結果,省去對大數據的掃描和運算,這就是Apache Kylin高性能查詢的基本實現原理。
如圖1所示,Apache Kylin會對SQL的查詢計划進行改寫,把源表掃描、多表連接、指標聚合等在線計算轉換成對預計算結果的讀取,極大減少了在線計算和I/O讀寫的代價。 而查詢所訪問的預計算結果保存在Cuboid當中(見圖1紅色方框),Cuboid大小隻和維度列的基數有關,和源數據行數無關,這使得查詢的時間複雜度可以取得一個量級的提升。
圖1 預計算查詢計劃
一個Cuboid對應著一組分析的維度,並保存了度量的聚合結果。Cube就是所有Cuboid的集合,如圖2所示,每個節點代表一個Cuboid。當查詢到達,Apache Kylin會根據SQL所使用的維度列在Cube中選擇最合適的Cuboid,最大程度地節省查詢時間。
圖2 Cube示意圖
Cube優化案例
社區不乏一些使用Apache Kylin的成功案例分享,但經常還會看到很多朋友遇到性能問題,例如SQL查詢過慢、Cube構建時間過長甚至失敗、Cube膨脹率過高等等。究其原因,大多數問題都是由於Cube設計不當造成的。因此,合理地進行Cube優化就顯得尤為重要。
這裡先分享兩個社區用戶進行優化的案例:
案例1 – 提升Cube查詢效率
背景:某智能硬體企業使用Apache Kylin作為大數據平台查詢引擎,對查詢性能有較高要求,希望提高查詢效率。
數據:
- 9個維度,其中1個維度基數是千萬級,1個維度基數是百萬級,其他維度基數是10w以內
- 單月原始數據6億條
優化方案:
- 數據清理:將時間戳欄位轉換成日期,降低維度的基數
- 調整聚合組:不會同時在查詢中出現的維度分別包含在不同聚合組(如崩潰時間、上傳時間等)
- 設置必須維度:把某些超低基數維度設為必須維度
優化成果:
- 查詢性能:提升5倍
- 構建時間:縮短30%
- Cube大小:減小74%
案例二 – 提升Cube構建效率
背景:某金融企業使用Apache Kylin作為報表分析引擎,發現Cube膨脹率多大、構建時間過長,希望對這一情況進行改善。
硬體:20台高配置PC伺服器
數據:事實表有100多萬條記錄,度量是某些列的平均值
優化方案:
- 維度精簡:去除查詢中不會出現的維度
- 調整聚合組:設置多個聚合組,每個聚合組內設置多組聯合維度
優化成果:
Cube優化原理
從以上案例可以看出,通過Cube調優可以顯著改善Apache Kylin的構建性能、查詢性能及Cube膨脹率。那麼這些改進的背後究竟是什麼原理呢?
為了深入理解Cube,首先要先了解Cuboid生成樹。如圖3所示,在Cube中,所有的Cuboid組成一個樹形結構,根節點是全維度的Base Cuboid,再依次逐層聚合掉每個維度生成子Cuboid,直到出現0個維度時結束。圖3中綠色部分就是一條完整的Cuboid生成路徑。預計算的過程實際就是按照這個流程構建所有的Cuboid。
圖3 Cuboid生成樹
通過這顆Cuboid生成樹,我們不難發現:當維度數量過多,就會導致Cuboid數量以指數級膨脹;如果維度基數過大,還會使所在的Cuboid結果集變大。這些都是影響Cube膨脹率和構建時間的重要因素。
但是,所有的Cuboid都是必要的嗎?實際上,在多數情況下,我們並不需要這裡的每一個Cuboid,因此需要對Cuboid生成樹做剪枝。剪枝可以從兩個方面入手:數據特性、查詢需求。首先介紹數據特性,考慮下圖的兩個Cuboid,左側Cuboid包含4個維度(ABCD),右側Cuboid包含3個維度(ABC),而兩個Cuboid都包含相同(或極度相近)行數的記錄,說明讀取兩個Cuboid結果的代價是一樣的,同時左側Cuboid除了具有右側Cuboid的查詢支持能力外,還能支持帶有維度D的查詢,因此右側Cuboid就可以被去除。
圖4 去除冗餘Cuboid
再考慮查詢需求,在報表或多維分析場景中,有些維度是每次查詢都會出現的,如年份;有些維度總是一起出現的,如開始時間、結束時間;有些維度間是有層級關係的,如商品分類或地理信息。充分利用查詢的這些實際需求也能去除不需要的Cuboid,例如:如果年份是必要的,那麼所有不包含年份維度的Cuboid都可以被去除;如果兩個維度總是同時出現,那麼這這些維度單獨出現的Cuboid就可以被去除。
在Apache Kylin中,可以通過設置Cube的維度組合規則來去除無用的Cuboid。首先,可以通過定義聚合組對維度分組,只在每個聚合組內生成Cuboid。此外,在單個聚合組內部,還可以設置維度組合規則,如:必須維度用於定義一定出現的維度、聯合維度用於定義一組同時出現的維度、層級維度用於定義一組有層級關係的維度,詳細的Cuboid生成規則如下圖所示:
圖5 聚合組規則
Cube優化工具
上文介紹了Cube設計和優化的基本原理,但是如何實踐是一個比較有挑戰的事情,需要操作者對這些原理的實現細節、數據特性、查詢需求都有較深理解。所謂工欲善其事,必先利其器。這裡介紹一個Cube優化的神器KyBot(https://kybot.io),可以通過可視化手段展現Apache Kylin中的各項統計指標,並進行智能化評分及規則,有助於快速定位查詢、構建瓶頸和尋找解決方案。
KyBot的使用也十分簡單,只需要簡單上傳包含日誌的診斷包,後台會自動對診斷包中的查詢、構建日誌等歷史進行分析,挖掘可能的Cube設計缺陷,通過可視化頁面直觀地展現出來。如果希望對日誌中的敏感信息(如IP地址等)進行脫敏保護,也可以簡單解決。
圖6 KyBot網站
尋找Cube設計缺陷
當KyBot分析完成,在Cube儀錶盤上就能看到Cube的診斷結果了,包括Cube評分、Cube排行、Cube詳情等。圖7的雷達圖展示的就是所有Cube的整體評分,包含查詢性能、構建性能、膨脹倍數、使用率、模型設計等5個維度。通過這個評分,就可以一眼對整個Apache Kylin的性能體現有一個直觀認識,也可以直觀地看出Cube優化的重要性和必要性。例如在這個例子中可以看出,雖然整體的查詢、構建性能較好,但模型設計依然有很大提升的空間。
圖7 Cube總體評分雷達圖
了解整體性能之後,還需要進一步縮小範圍尋找可優化的Cube,通過圖8的Cube排行就可以。圖中從膨脹倍數、查詢次數、慢查詢次數對Cube進行了排名,排在首位的就是在這一排名中最需要優化的Cube,例如,膨脹倍數排名第一個Cube的膨脹倍數遠遠高於其他Cube,說明有巨大的優化空間,如果對數據存儲或構建時間有要求,就可以先從這個Cube入手進行優化。同樣的,如果對查詢效率有要求,就可以從慢查詢次數排行入手。
圖8 Cube排行
鎖定了優化目標,單擊這個Cube的柱狀圖查看Cube詳情,如圖9所示。圖中1區域是當前Cube的評分,可以直觀看出Cube在模型設計和查詢性能方面有缺陷,其中模型設計的優劣來自對Cuboid重合率和查詢匹配度的統計。評分下方的柱狀圖顯示Cuboid重合率排名,Cuboid重合率代表一個Cuboid和他父節點Cuboid行數的比例,如果重合率接近100%,根據上文「Cuboid優化原理」一節,這個Cuboid是可以被去除的。根據圖中的例子,有800多個Cuboid重合率高於90%,都是可以被去除的。
圖9 Cube調優
接下來進入實際操刀環節,先來看模型設計的問題。圖中2區域是Cuboid層級的樹狀圖,在根節點(Base Cuboid)的8個子節點裡,發現有6個節點的重合率超過了98%,且行數超過了1千萬,說明這些Cuboid即使比父Cuboid相比少了一個維度,但依然沒有減少結果集數量,換句話說,少掉的這個維度收縮力較弱,原因可能是因為這個維度基數較低,或者Cuboid中包含超高基數的維度。通過單擊第一個子Cuboid,在區域3查看各個維度的詳細信息,不難發現,該Cuboid並沒有超高基數維度,而和父級Cuboid差異的維度YYYYMM基數很低。雖然YYYY和YYYYMM兩列已是層級維度,但兩個維度的基數均很低。同理,發現CATA1_ID和CATA2_ID的組合也是如此,如下圖所示。鑒於YYYY、YYYYMM、CATA1_ID、CATA2_ID這4個維度的收縮力較弱,可以合併成一個聯合維度。
圖10 Cube維度信息
此外,還有多個基數較低的維度(LOCATION、TYPE、PIPE_ID)也有收縮力較弱的問題,也應合併成一組聯合維度。這樣,如下圖所示,由於聯合維度的引入使Cuboid數從28減小到25,有效地降低了Cube膨脹率、提升構建性能,同時又不影響查詢性能。
圖11 設置聯合維度
最後來看查詢效率的問題。如下圖所示,發現這個Cube中有一個維度WORKER_ID基數在1300以上,且被設為必須維度。但是在使用統計中看到,這個維度並沒有被SQL用到過,這些SQL本身可以訪問一個體量較小的Cuboid,但由於WORKER_ID被設為必須維度,所有的Cuboid都會包含這個1300+基數的維度,導致所有Cuboid記錄數膨脹,造成查詢性能普遍較差。因此,取消這一維度的必須維度設置,勢必能夠大大提升Cube的查詢性能。
圖12 去除不恰當的必須維度
尋找Cube構建瓶頸
在Apache Kylin中,Cube的構建是通過一系列MapReduce和Spark任務完成的,其中MapReduce占多數。在KyBot上也可以看到Cube構建任務的可視化過程,如下圖所示,就是一個Cube構建的生命周期,其中每一條綠色泳道代表了構建任務的一個步驟,泳道最長的一步說明耗時最大,如果要優化,就可以首先研究這一步。
圖13 Cube構建生命周期
如果上傳了這個任務的任務診斷包,還可以繼續查看每一個MapReduce步驟的可視化過程。單擊這個耗時最久的泳道,就會打開下圖所示的MapReduce生命周期,在這個例子中,我們發現同一時間只有一個Task在運行,第一個task開始前還有較長的等待時間,說明集群資源可能較為緊張。如要優化,建議檢查集群資源配置和調度。
圖14 MapReduce任務生命周期
尋找查詢瓶頸
查詢是Apache Kylin的強項,但也存在種種因素導致某些查詢變慢。查詢性能一般通過整體的性能、並發統計數據來體現,KyBot的查詢儀錶盤可以直觀展現不同維度的查詢統計信息。如下圖所示,這裡可以看到查詢響應時間的90百分位和95百分位、不同響應時間分布、每日性能變化等,用於直觀把握查詢性能的整體表現;下方的查詢次數、人均查詢次數、每日查詢次數等直觀展現Apache Kylin作為查詢服務的使用率和並發數。
圖15 查詢統計圖
為了提升Apache Kylin的查詢性能,首先要定位慢查詢。查詢儀錶盤下方的查詢明細列表中可以看到慢查詢列表,並從這裡進入一個查詢的詳情頁面,如下圖所示:
圖16 查詢詳情頁
在查詢的詳情頁,區域1是該查詢的歷史執行記錄,通過單擊圖中的空心圓圈可以定位到某次查詢記錄。區域2是該查詢擊中的Cuboid及Rowkey的使用情況,綠色代表這個Rowkey作為查詢的過濾條件,藍色代表Rowkey作為查詢的GROUP BY欄位,白色代表出現在Cuboid上但沒被查詢用到的Rowkey。因為Apache Kylin使用HBase作存儲引擎,所以參與過濾的Rowkey排在Cuboid前面會對查詢性能有幫助。因此,藍綠顏色的順序就顯得尤為重要了。圖17是一個需要優化的查詢例子,綠色Rowkey在末尾,可能影響HBase過濾的效率;中間有6個白色Rowkey,是因為這個6個維度被設為了必須維度,其中還有4個是高基數維度,會帶來較高的存儲掃描和在線計算代價,影響查詢的效率。優化方案是取消必須維度的設置或改用聯合維度。
圖17 待優化查詢(1)
圖16的區域3是該查詢執行的生命周期,其中綠色泳道代表Apache Kylin查詢節點的線程,藍色泳道代表HBase節點的執行線程。圖18是一個需要優化的例子,圖中兩條藍色泳道長度區別很大,是由於數據切分Region不平衡導致不同Region Server負載差異較大。因此可以通過設置Shard By欄位或調整Region切分相關的參數來加速查詢。
圖18 待優化查詢(2)
總結
本文著重介紹了Apache Kylin中對Cube和查詢進行優化的原理、工具、方案和案例,希望能夠幫助使用Apache Kylin的朋友解決工作上的棘手問題。查詢需求可能隨著業務發展而不斷變化,而Cube優化就是不斷保證Cube性能的有效手段。為了更加高效地完成調優,使用KyBot是一個最簡單的方式,未來的KyBot也會更加自動化和智能化。最後,希望「麒麟神獸」在每一片大數據草原上都能施展最大的威力!
作者:李棟,Kyligence Inc技術合伙人兼高級軟體架構師,Apache Kylin Committer & PMC Member,專註於大數據技術研發,KyBot技術負責人。畢業於上海交通大學計算機系;曾任eBay全球分析基礎架構部高級工程師、微軟雲計算和企業產品部軟體開發工程師;曾是微軟商業產品Dynamics亞太團隊核心成員,參與開發了新一代基於雲端的ERP解決方案。
推薦閱讀:
※PHP寫的API如何防止拒絕服務攻擊?
※php-cgi和php-fpm有什麼關係?
※Web 測試 有沒有比Apache Jemeter更好的工具,windows或者macos上的?
※開發人員學Linux(8):CentOS7編譯安裝Subversion1.9.5及Apache2.4.25並集成
TAG:Apache |