Impala內存優化實戰案例

Impala內存優化實戰案例

暢遊DT時代(李珂) · 2016-03-26 01:23

Impala內存優化實戰案例

文章來源:中國聯通網研院網優網管部——IT技術研究團隊

作者:李珂


一. 引言

    Hadoop生態中的NoSQL數據分析三劍客Hive、HBase、Impala分別在海量批處理分析、大數據列式存儲、實時交互式分析各有所長。尤其是Impala,自從加入Hadoop大家庭以來,憑藉其各個特點鮮明的優點博取了廣大大數據分析人員的歡心。

    Impala通過主節點生成執行計劃樹並分發執行計劃至各節點並行執行的拉式獲取數據的工作方式,替代了Hadoop中傳統的MapReduce推式獲取數據的工作方式,計算的中間結果不寫入磁盤,及時通過網絡以stream的方式傳遞,交互性和實時性更強;Impala不花費額外的精力管理元數據,而是使用Hive的Metastore進行元數據管理,能夠直接訪問存儲在Hadoop的HDFS和HBase中的PB級大數據;Impala採用塊的方式將元數據加載到內存進行運算,相比Hive、HBase而言運算性能有了較大的提升;Impala提供SQL語義,相比HBase對於用戶而言使用方便快捷並且簡單實用,無需其他編程語言,只需使用SQL語句即可完成複雜的數據分析任務;Impala還繼承了Hadoop的靈活性、伸縮性和經濟性,具有分佈式本地化處理的特性以避免網絡瓶頸。

    說了Impala這麼多優點,難道它真是一點缺點沒有的一款“完美”的分析工具嗎?

    非也!在一年以上的Impala海量數據分析、web應用開發實戰經驗中,Impala也陸陸續續暴露出了一些致命的問題:

  • “啃內存”一族,對於內存的依賴過於嚴重,內存溢出直接導致技術任務的失敗。

  • “閹割版”SQL——不支持UDF,不支持UPDATE/DELTE操作,不支持同一SELECT中多個DISTINCT。

  • 權限角色等安全機制的實現需要額外的安全組件,管理配置較複雜。

    但是瑕不掩瑜,通過研究Impala的工作機制及錯誤日誌,我們發現Impala的上述缺陷都可以通過一些優化方案和替代措施得以很好的解決。通過合理的優化將Impala的性能最大化的挖掘,利用Hadoop生態開源的優勢與商業化的NewSQL數據庫相對抗,在節省軟件成本的同時獲取不遜於NewSQL數據庫的分析性能。

    由於篇幅有限,今天我們先來談一談Impala內存溢出問題的優化。

二. 告別“Memorylimit exceeded”——Impala內存優化

SQLOperations that Spill to Disk

    在介紹Impala內存優化技巧之前,我們先來看一下Impala官方針對內存溢出問題所作出的努力。Impala從Impala 1.4 for CDH4、CDH5.1版本開始新增了“SQL Operations that Spill to Disk”功能,即當Impala內存運算溢出時轉移到磁盤進行運算,雖然在計算時需要佔用臨時的磁盤空間,增加了磁盤I/O,導致運算時間遠高於純內存運算,但至少解決了內存溢出時分析任務直接失敗這一“0”容錯的致命問題。

    該功能的開啓也非常簡單,只需在impalashell中執行“setDISABLE_UNSAFE_SPILLS=0”或者“setDISABLE_UNSAFE_SPILLS=FALSE”命令即可。當設置DISABLE_UNSAFE_SPILLS參數的值爲0(FALSE)時,內存運算瀕臨溢出時轉爲磁盤運算;設置爲1(TRUE)時,當內存溢出時直接報內存溢出“Memory limit exceeded”錯誤。下圖是筆者在Impala 2.2.0 for CDH5.4.1版本對此功能進行測試的截圖:


    
可以看到,在開啓DISABLE_UNSAFE_SPILLS參數時,禁用了內存溢出寫入磁盤的功能,查詢任務失敗;但關閉DISABLE_UNSAFE_SPILLS參數時,開啓了內存溢出寫入磁盤的功能,雖然查詢任務用時1225秒,但完成了該查詢任務。

    在Cloudera manager的Impala查詢監控界面中,我們可以看到兩次查詢所消耗的資源情況:


    
在測試中,筆者將集羣Impala節點的內存限制爲3.5GB,可以看到該查詢語句累積內存使用峯值爲3.6GB,產生“Memory limit exceeded”錯誤。而開啓了“SQL Operations that Spill to Disk”功能後,使用內存峯值改變爲2.3GB,計算所需多餘的內存都轉爲至磁盤進行運算(在集羣三個DataNode節點各寫入了10G的臨時數據),避免了“Memory limit exceeded”報錯,成功完成了查詢。

    內存溢出的問題僅憑藉這一招就解決了?其實不然!

    實際上,Impala官方也承認該功能存在很多限制,並且還建議用戶儘可能的規避觸發“Spill to Disk”功能。該功能目前存在的限制包括:

  1. 不是所有的SQL語句都能觸發,例如union關鍵字還是會觸發內存溢出錯誤;

  2. 各個節點的內存峯值限制不能過低,低於運算所需分配給各個節點的最小內存;

  3. 運算explain輸出的各個節點預估內存不能過分高於各個節點的實際物理內存;

  4. 當觸發“Spill to Disk”功能時有其他併發查詢,仍會觸發內存溢出錯誤;

  5. 對磁盤的空間有一定的要求,磁盤運算的數據會寫入到impala各個節點的臨時目錄下,增加了磁盤I/O,並且會引發不可控制的磁盤佔用。

    無論是官方建議,還是實際使用經驗而言,“Spillto Disk”不是一個長遠之計。還是應該通過優化SQL查詢、修改系統參數、提高硬件配置等方式來解決內存溢出的發生。

優化SQL查詢

    SQL優化不僅是一個成熟的分析、開發團隊需要具備的基本素質,更能最大限度的挖掘Impala集羣的性能,在數據分析時達到事半功倍的效果。下面介紹一下Impala SQL優化的四大法寶:

    法寶一:Compute Stats

    COMPUTE STATS(DDL)完成對錶、分區、列的數據量和數據分佈信息的蒐集,蒐集到的相關信息會被存儲在元數據庫中。看似只是Impala中一條獲取表的統計信息的簡單語句,但在整個分析任務調度過程中卻起着相當重要的作用。該語句獲取的統計信息不僅在Impala對JOIN、GROUP BY、ORDER BY、UNION、DISTINCT等資源高消耗的查詢進行優化時會使用到,而且對HBase的表也同樣起作用。

    在Impala的分析任務中,無論是數據庫中的原始表、中間表、結果表還是查詢用到的海量數據表或者影響性能的關鍵表,建議在生成表之後執行COMPUTE STATS table_name命令對錶的相關信息進行統計,集羣會根據統計信息自動選擇優化的查詢方案。越是規模大的表(GB、TB級以上)統計命令執行時間越長,統計完成後的查詢優化效果越是明顯。

    在執行完成統計信息命令後,使用SHOW TABLE STATS table_name命令,檢測確認統計信息是否可用,輸出表的詳細統計信息。

    Compute Stats究竟有多重要?一起看看下面這個例子就知道了。

    在做用戶畫像專題分析的過程中,我需要將用戶基礎信息表(3億條)、用戶語音業務信息表(1.6億條)、用戶數據業務信息表(9千萬條)三張大表進行關聯彙總,在使用Compute Stats命令前任務耗時50分鐘,各節點內存峯值佔用140GB,最終分析結果出現BUG,存在多條重複記錄的情況,任務所消耗的資源情況如下圖所示:


    
在對三張大表分別執行ComputeStats命令之後,再次執行該分析任務,任務耗時32分鐘,各節點內存峯值僅爲17GB,分析結果正常,任務所消耗的資源情況如下圖所示:


    
可以看到Impala各節點在獲取到表的統計信息後,能夠更加合理的生成任務執行計劃並完成任務的調度,不僅降低了產生“Memory limit exceeded”錯誤的風險,而且避免了內存消耗過大導致分析任務異常的BUG。

    值得一提的是在實際應用過程中,經常會有一些規模較大的表(TB級上千億條記錄)在執行COMPUTE STATS命令時假死無法完成統計任務的情況。針對這種情況,有兩種方法可以解決:一是從Impala 2.1 for CDH5.3版本新增了COMPUTE INCREMENTAL STATS(DDL)命令,將大表分區存儲後,可用該命令增量的對各分區進行統計,並且當分區變動時只對變化部分進行掃描,並更新相應的統計信息;二是對於沒有升級到高版本的Impala集羣或是物理資冶受限的增量統計也無法完成統計任務的情況,我們可以通過手動更新表的統計信息、設置分區的統計信息等方式解決。如下圖示例,首先對錶count(*),然後通過alter table table_name settblproperties('numRows'='n')命令(n表示count(*)獲取到的具體記錄條數)手動設置表的記錄條數,再次查詢表的統計信息,發現Impala集羣已經成功獲取到表的統計信息了。


    法寶二:執行計劃

    通過在SQL語句前加入“EXPLAIN”關鍵字,可以返回該語句的執行計劃。執行計劃從底層顯示Impala如何讀取數據,如何在各節點之間協調工作,組合並傳輸中間結果,並獲得最終結果集的全過程。

    根據執行計劃,可以判斷這個語句的執行效率,如果發現效率過低,可以調整語句本身,或者調整表結構。例如可以通過改變WHERE查詢條件、對JOIN查詢使用hints、引入子查詢、改變表的連接順序、改變表的分區、蒐集表及列統計信息或者其他方式來對語句進行性能優化。


    
上圖是對一個查詢語句調用EXPLAIN查看執行計劃,對於輸出結果自底向上按序閱讀:

    (1)最後一部分內容展示了讀取的總數據量等底層的詳細信息。通過讀取的數據量,我們可以判斷分區策略是否有效,並結合集羣大小預估讀取這些數據需要的實際等。

    (2)可以看到執行過程中聚合、排序、統計函數、交互的順序及具體執行細節,可以從更高級別看到中間結果在不同節點間的流向。

    (3)我們可以看到操作是否被Impala不同的節點並行執行,以及各節點所需內存預估值。

    (4)通過配置EXPLAIN_LEVEL參數,可以瞭解到更詳細的輸出信息。取值從0~3,對應的執行計劃信息越來越詳細。

    法寶三:PROFILE查詢信息

    使用PROFILE語句可以輸出最近執行的SQL查詢的更詳細更底層的信息。在查詢執行完成後,無論查詢成功與否,輸入PROFILE命令即可輸出查詢的詳細信息。它包括了執行該查詢每個節點讀取的物理字節數,使用的最大內存量等信息。通過這些信息,我們可以判斷查詢是IP消耗型的、CPU消耗型的、網絡消耗型的,或者受性能低下節點的影響,從而可以檢查某些推薦的配置是否生效等。

    Profile輸出的查詢信息內容包括:

    (1)執行查詢的查詢狀態、查詢起始時間、查詢語句、提交查詢任務的Impala節點等基礎信息:


    
(2)查詢的執行計劃和步驟:


    
(3)各個步驟執行情況的統計信息,包括各節點的執行平均時長、最大時長、讀取數據量、內存峯值等信息:


    
(4)各個步驟執行情況的詳細信息及每個步驟分配到各個節點執行的詳細信息(由於該部分信息過多,截圖省略)。

    在運行一個查詢之後,使用PROFILE命令從底層確認該查詢的IO、內存消耗、網絡帶寬佔用、CPU使用率等信息是否在我們期望的範圍之內,若不是最優方案,則有的放矢通過對SQL語句進行調優、調整節點配置等方式進行優化。

    法寶四:結構優化

    在使用了上述三個法寶之後若Impala內存溢出問題還是沒有解決的話,那麼就有必要從結構方面考慮一下優化措施了。

    (1)Parquet表存儲

    爲Impala中源數據、中間表、結果表選擇合適的存儲結構。Impala默認是建立TEXT格式的表存儲,而對於海量數據的存儲,優選Parquet格式的存儲方式。在建表時顯示的指定以Parquet格式建表,並且避免使用INSER...VALUES語句向Parquet表中插入數據。因爲這種方式每插入一行數據就會在HDFS上產生單獨的一個小數據文件,會降低數據查詢的並行度從而影響查詢速度。

    (2)分區技術

    當表的數據量非常龐大或者表總是按照某些特定的列進行查詢時,通過分區技術能極大的提升Impala的查詢速度。在分區時分區列要有一定的區分度,也就是要包含一定數據的非重複值。根據實際情況選擇分區的粒度,儘量保證每個分區的數據都大於1GB或者是1GB的倍數。只有分區的粒度使數據文件的大小合適,才能充分利用HDFS的IO批處理性能和Impala的分佈式查詢。

    (3)SQL語句

    SQL語句性能對最終任務的執行效率有着直接的影響。以下是SQL優化的一些“經驗之談”:

  • 關聯條件儘量避免用過長的string進行關聯,儘可能使用數字進行關聯。

  • 對龐大任務拆分後“分而治之”,用建立中間表逐步執行的方式替代多層嵌套任務。

  • 如果參與關聯的表的統計信息不可用,或者Impala自動選擇的連接順效率很低,可以在SELECT關鍵字後使用STRAIGHT_JOIN關鍵字按照“大表在左,小表在右”的原則手動指定表連接順序。

  • 使用Hints手動從底層調整SQL查詢的工作方式,Hints的使用方式爲使用[]將特定的Hints括起來放在SQL語句中。

  • 大表與小表的關聯時,使用Hints指定[BROADCAST]爲連接方式;處理大表之間的關聯時,使用Hints指定[SHUFFLE]爲連接方式。 

優化集羣系統資源

    除了從SQL查詢方面進行優化之外,還可以通過對Impala集羣系統在資源配置方面加以優化,做到“雙管齊下”。Impala的准入控制功能是一個輕量級的、分佈式資源控制機制,它可以限制查詢使用的內存段大小,並行執行的查詢數量等。利用該功能對系統配置進行優化視具體集羣環境而定,優化的思路包括:

  • 合理對impalad進程制定-MEM_LIMIT選項來限制預留給查詢的內存大小。

  • 配置YARN進行動態分配,合理制定Impala與Hadoop其他組件的內存分配關係。

  • 針對不同的用戶組的應用請求,配置Cgroup資源池機制來隔離資源的使用。

  • 若內存溢出大多出現在並行小查詢數過多而非少量內存佔用較高的大查詢時,通過Impala admission control功能限制併發查詢。

  • 配置查詢隊列,新的查詢請求到來時若系統資源已達到峯值,則被放入等待隊列,在之前查詢執行完成並釋放相關資源後,等待隊列中的查詢才能夠被執行。

  • 使用准入控制來控制集羣中Impala作業對併發和內存的消耗,使用YARN控制Hadoop其他組件的資源消耗。

三. 寫在後面

    Impala作爲一款開源的大數據分析引擎,其自身存在的一些缺陷是可以接受的。通過採用一些合理的優化方案,挖掘它的潛力,當真正“玩轉”之後,Impala一定會帶給你意想不到的驚喜。

-END-


轉載地址:http://www.wtoutiao.com/p/1b1Bxop.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章