硬核干貨 | 基于Impala的網(wǎng)易有數(shù)BI查詢優(yōu)化總結(jié)
有數(shù)BI + Impala遇上慢查詢
在網(wǎng)易有數(shù)大數(shù)據(jù)平臺架構(gòu)中,有數(shù)商業(yè)智能(BI)產(chǎn)品提供了數(shù)據(jù)大屏、有數(shù)報告和自助取數(shù)等服務(wù)。

自助取數(shù)面向的用戶是數(shù)據(jù)分析師,有數(shù)報告所面向的用戶是BI工程師,允許用戶直接通過拖拽UI界面的各種控件來獲取所需的取數(shù)結(jié)果或數(shù)據(jù)報告,能夠減少數(shù)據(jù)開發(fā)等相關(guān)工程師的工作量,大大提高分析師取數(shù)的效率和BI報告制作效率。

目前,有數(shù)產(chǎn)品在包括網(wǎng)易云音樂、嚴(yán)選、傳媒等在內(nèi)的網(wǎng)易集團內(nèi)部業(yè)務(wù),以及包括德邦快遞、名創(chuàng)優(yōu)品、溫氏集團、古茗等外部客戶的業(yè)務(wù)上均大規(guī)模使用。
世上武功,唯快不破。對于自助取數(shù)和有數(shù)報表,用戶體驗非常重要的一點就是要快。目前有數(shù)產(chǎn)品主要使用Impala作為數(shù)據(jù)查詢引擎,相比Presto等其他開源OLAP查詢引擎,Impala具有明顯的性能優(yōu)勢。區(qū)別于社區(qū)版Apache Impala,有數(shù)使用的是網(wǎng)易大數(shù)據(jù)的Impala增強版。
在有數(shù)大規(guī)模使用中,音樂等業(yè)務(wù)場景也呈現(xiàn)出了有數(shù)+Impala的不少問題,包括查詢錯誤較多、部分查詢較慢等。針對這些問題,Impala內(nèi)核小組與業(yè)務(wù)、大數(shù)據(jù)產(chǎn)品團隊合作進行了大量優(yōu)化,提高了查詢成功率,減少了慢查詢數(shù)量。
后面我們會結(jié)合案例詳細(xì)分析如何優(yōu)化。開始前,先介紹優(yōu)化所用的2個工具:
在Impala這一側(cè),我們進行問題分析,尋找優(yōu)化方法的主要工具是 Impala管理服務(wù)器,這部分在下一小節(jié)展開介紹;
另一個工具是有數(shù)報告,是的,我們用有數(shù)BI產(chǎn)品來對有數(shù)查詢進行優(yōu)化,將基于Impala管理服務(wù)器得到的分析結(jié)果制作成直觀的圖表報告。在優(yōu)化過程也逐漸體會到有數(shù)產(chǎn)品的強大。
Impala管理服務(wù)器
Impala是個Hadoop生態(tài)下的MPP查詢引擎,以性能著稱,其核心組件包括Catalog,Statestore和Impalad,Impalad根據(jù)是否接收客戶端查詢請求又可分為coordinator/executor。Impala的系統(tǒng)架構(gòu)如下所示:

社區(qū)版Impala運維上的不足
目前社區(qū)版Impala在運維方面還存在不少短板。主要體現(xiàn)在如下方面:
社區(qū)版Impala為每個coordinator提供了webui界面,能夠查看該coordinator正在執(zhí)行和最近已完成的查詢信息等。但Impala沒有提供集群層面的查詢視圖,即沒有將各coordinator節(jié)點的查詢信息匯總到一個webui上。在觀察集群查詢狀態(tài)時需要同時打開各個coordinator的webui并頻繁切換;
coordinator的webui上展示的查詢信息是非持久化的,一旦進程重啟,這些信息就丟失了,而上線升級、系統(tǒng)bug等因素,進程重啟是不可避免的;
coordinator的查詢信息非持久化帶來的另一個問題是:即使進程未重啟過,其所能緩存的查詢個數(shù)也是有限的,通過--query_log_size參數(shù)進行配置;
coordinator緩存的信息是在進程的地址空間內(nèi),未暴露出來。外部工具無法獲取這些信息進行分析。
管理服務(wù)器功能
針對上述問題,網(wǎng)易大數(shù)據(jù)團隊在Apache Impala社區(qū)版基礎(chǔ)上開發(fā)了Impala集中式管理模塊,即Impala管理服務(wù)器(managerd)。其主要功能包括:
匯總Impala集群中各coordinator節(jié)點正在執(zhí)行和已完成的查詢,提供統(tǒng)一的web端查詢視圖。這樣在需要查找集群中正在執(zhí)行或已完成的查詢時,無需打開各coordinator的web界面;
將歷史查詢信息持久化到MySQL和對象存儲上,有效防止進程重啟或查詢數(shù)量過多導(dǎo)致查詢丟失問題。
管理服務(wù)器保存了集群上已執(zhí)行的所有歷史查詢信息,包括查詢基礎(chǔ)信息表basic_info和查詢明細(xì)表detail_info,如下所示:

detail_info相比basic_info的字段更少,但有多個mediumblob字段,其中包含了更豐富的查詢信息。

detailinfo表有個profile字段,存儲了NOS上的key,該key對應(yīng)的NOS對象保存了完整的查詢profile文件。
profile文件
profile文件是深入分析查詢整個執(zhí)行過程的關(guān)鍵信息,包括查詢的時間線(timeline),各個執(zhí)行片段的counter信息、查詢涉及的表是否有統(tǒng)計信息等。

使用痛點及優(yōu)化
如前所述,我們可以把業(yè)務(wù)痛點分為慢查詢和查詢錯誤兩類問題。下面就結(jié)合生產(chǎn)環(huán)境來舉例說明具體存在哪些問題。
慢查詢原因分析和優(yōu)化
出現(xiàn)慢查詢的原因很多,下面分別從Impala、有數(shù)BI產(chǎn)品和HDFS等維度來進行說明。
1.Impala相關(guān)
統(tǒng)計信息缺失
與主流的數(shù)據(jù)庫和數(shù)倉查詢引擎一樣,Impala也是基于代價模型進行執(zhí)行計劃優(yōu)化(CBO)。只有獲取足夠的統(tǒng)計信息,才能支撐Impala選取較優(yōu)的執(zhí)行計劃。
但Impala作為一個查詢引擎,往往不負(fù)責(zé)schema的創(chuàng)建和數(shù)據(jù)的導(dǎo)入,因此,也就無法在數(shù)據(jù)導(dǎo)入時計算統(tǒng)計信息。作為一個基于CBO的查詢引擎,若用戶不手動執(zhí)行compute [incremental] stats計算統(tǒng)計信息,Impala的查詢性能是要打折扣的。下圖為統(tǒng)計缺失時的一個執(zhí)行計劃,可以看到531.35G的表分區(qū)作為右表被廣播(broadcast)到集群的其他節(jié)點上進行join操作。


優(yōu)化與改進
在對查詢所涉及的表進行統(tǒng)計信息計算后,再次進行查詢,join方式變?yōu)榉謪^(qū)模式(partitioned)。


優(yōu)化效果是顯而易見的,除了性能得到了提升(從10分鐘超時變?yōu)?6s)。資源的消耗也急劇減低(詳見04:hash join的mem-estimate值)。
因統(tǒng)計信息缺失導(dǎo)致的慢查詢是普遍存在的,線上集群通過手動配置需要進行統(tǒng)計信息計算的表,對其跑compute stats腳本的方式來計算統(tǒng)計信息,作為臨時的優(yōu)化方式。
目前,我們已經(jīng)依托Impala管理服務(wù)器開發(fā)了基于歷史查詢數(shù)據(jù)的自動統(tǒng)計信息計算功能,能夠根據(jù)所配置的參數(shù)自動選擇待處理的表,將其記錄到compute_stats_info表中。

管理服務(wù)器通過后臺線程讀取這些表記錄并進行統(tǒng)計信息計算。預(yù)計Q1上線使用。
元數(shù)據(jù)緩存未命中
除了基于CBO進行執(zhí)行計劃選擇外,Impala通過將表元數(shù)據(jù)緩存在本地來提升查詢性能,如將Hive表的元數(shù)據(jù)從Metastore(hms)加載到Catalogd和coordinator上,在為查詢確定執(zhí)行計劃時就無需花時間通過RPC調(diào)用從hms獲取所需的表元數(shù)據(jù)。
但由于Hive表會持續(xù)進行元數(shù)據(jù)更新,比如表分區(qū)的增加、刪除和重命名,修改表屬性等。這些都會導(dǎo)致Impala上緩存的元數(shù)據(jù)版本過舊,網(wǎng)易Impala版本增加了元數(shù)據(jù)同步功能,在hms側(cè)有元數(shù)據(jù)更新時,會刷新(refresh table)或失效(invalidate metadata table)緩存的元數(shù)據(jù)。
問題原因及優(yōu)化
元數(shù)據(jù)同步功能解決了元數(shù)據(jù)版本過低導(dǎo)致查詢出錯問題,但會失效緩存的元數(shù)據(jù),導(dǎo)致性能下降。而且Hive表支持自定義屬性,即用戶可以增加一些具有特殊用途的表狀態(tài)信息,比如網(wǎng)易大數(shù)據(jù)平臺的元數(shù)據(jù)中心可為表增加訪問次數(shù)等統(tǒng)計,舉例如下:
'metahub.table.accessCount'='xxx', 'metahub.table.readCount'='xxx','metahub.table.readTimes'='xxx', 'metahub.table.referCount'='xxx',元數(shù)據(jù)中心會調(diào)用hms的alter table接口以較高的頻次更新這些信息(采樣發(fā)現(xiàn),在15分鐘內(nèi)多達191次)。但其實這些信息對于Impala并沒有作用,不會對Impala執(zhí)行計劃產(chǎn)生影響。如前所述,alter table操作會觸發(fā)Impala側(cè)緩存失效,導(dǎo)致查詢時需重新加載。

上圖所示為一個總執(zhí)行時間21.5秒的查詢,其中11秒花在從hms加載表元數(shù)據(jù)上。
在大數(shù)據(jù)開發(fā)團隊的支持下,已能夠識別這些對Impala沒有影響的alter table操作并將其過濾掉,從而提高查詢的緩存命中率。
目前仍有較多必要的alter table操作場景會導(dǎo)致元數(shù)據(jù)失效,比如每天的離線數(shù)據(jù)產(chǎn)出。下一步,我們計劃通過優(yōu)化元數(shù)據(jù)更新的方式,及時收集因為各種原因?qū)е碌脑獢?shù)據(jù)緩存失效,通過后臺線程將其重新加載到緩存中。
2.有數(shù)BI查詢相關(guān)
用戶采用在有數(shù)界面拖拽控件的方式取數(shù)或制作圖表,有數(shù)產(chǎn)品需要將其轉(zhuǎn)換成Impala等查詢引擎支持的SQL語句。有數(shù)生成的SQL是否合理,對查詢性能具有重要的影響。下面列舉SQL查詢的優(yōu)化案例。
問題舉例
時間/日期轉(zhuǎn)換導(dǎo)致性能問題
就公司內(nèi)部而已,事實表的數(shù)據(jù)一般以時間作為分區(qū)字段,如每天一個分區(qū),分區(qū)字段類型為字符串。在分析報告中,經(jīng)常需要將時間字段轉(zhuǎn)換為時間戳類型,或進一步截取為分鐘、小時、天、周、月等粒度。如下所示:

諸如此類,需要對每條記錄都一一進行多個時間轉(zhuǎn)換處理操作,勢必會影響查詢的性能。下面是個是否進行時間轉(zhuǎn)換的查詢性能對比。

大查詢拖慢HDFS掃描性能
HDFS掃描性能往往會成為查詢瓶頸,除了因與其他如離線分析等業(yè)務(wù)共用一套存儲外,還有個原因是Impala下發(fā)了大量需掃描過多數(shù)據(jù)的查詢語句。
有些業(yè)務(wù)表的單分區(qū)/天數(shù)據(jù)量超過500G,某些有數(shù)查詢的分區(qū)范圍指定過大或沒有指定分區(qū),比如1個季度或干脆不限定分區(qū),則單個查詢至少需掃描50+TB數(shù)據(jù)量。下圖就是個案例。

更加嚴(yán)重的是,對于像有數(shù)這種BI報表產(chǎn)品,同個報告可能會包含多張相似的報表,類似的查詢往往都是成批出現(xiàn)的,影響更大。

產(chǎn)品側(cè)優(yōu)化
包括上述例子在內(nèi)的多個SQL查詢相關(guān)問題,在有數(shù)版本迭代過程中逐步得到了優(yōu)化,比如下圖為在有數(shù)7.3版本所做的2個優(yōu)化。

3.HDFS存儲相關(guān)
該問題又可分為2種,分別是訪問HDFS NameNode(NN)獲取文件元信息和從DataNode(DN)讀取文件數(shù)據(jù)。(需要注意的是,HDFS瓶頸是相對的,分場景的。對于Impala查詢來說可能是瓶頸,但對于離線批處理任務(wù)來說,可能同樣的性能表現(xiàn)并不構(gòu)成瓶頸)。本文主要討論DN相關(guān)問題及優(yōu)化。
小文件問題 單文件過小,且文件數(shù)太多,導(dǎo)致無法通過順序IO連續(xù)讀取大數(shù)據(jù)塊,需要重復(fù)走打開文件+讀取數(shù)據(jù)的流程,效率較低;線上某些表存在較嚴(yán)重的小文件問題。如下所示例子,文件大小僅為10+MB,線上個別表的文件大小甚至僅為KB、Byte級別。

分區(qū)過大 一般情況下,數(shù)據(jù)掃描的最小粒度是分區(qū)級別,分區(qū)越大則需掃描的數(shù)據(jù)量大。下圖所示某表,每天一分區(qū),單分區(qū)文件數(shù)1k+,分區(qū)大小400+GB,共有200+分區(qū)。也就是說,如果需要分析1個星期數(shù)據(jù),需掃描近3TB,若分析1個月,需掃約15TB。

表存儲格式 SQL On Hadoop查詢引擎查詢Parquet或ORC格式的表文件時性能是最好的,如對Impala來說,對于Parquet或ORC格式,Runtime Filters(RF)特性的優(yōu)勢能夠充分發(fā)揮,而對于TEXT文件格式,RF僅能作用在分區(qū)表上。下圖所示為一張TEXT格式的100+G非分區(qū)表,該集群每日慢查詢中有不小比例與該表相關(guān)。

數(shù)倉治理
對于DN相關(guān)的性能問題,涉及數(shù)倉治理,目前主要依賴業(yè)務(wù)的數(shù)倉團隊配合基于實際的業(yè)務(wù)場景進行優(yōu)化。對于TEXT表,建議業(yè)務(wù)盡可能修改為Parquet格式。
對于小文件問題。首先應(yīng)該合理配置數(shù)據(jù)生產(chǎn)/導(dǎo)入并發(fā)度,盡量減少小文件的產(chǎn)出的機率;其次,對于已存在的小文件,應(yīng)在分區(qū)內(nèi)進行適當(dāng)?shù)暮喜?;再次,對于每個分區(qū)的總數(shù)據(jù)量過小的情況,應(yīng)該考慮不對表進行分區(qū)。
對于分區(qū)過大問題??煽紤]進行數(shù)據(jù)清洗提質(zhì),去除其中無價值的數(shù)據(jù)。據(jù)了解,音樂有8億+用戶,一般情況,會計算分析每個用戶相關(guān)行為或推薦數(shù)據(jù)生成事實表,但這其中有一定比例的用戶是不活躍的,甚至是多年未登錄的。對于某些用戶相關(guān)事實表,可以考慮去掉不活躍用戶的數(shù)據(jù),從而減少每個分區(qū)內(nèi)的數(shù)據(jù)量。
同時,大數(shù)據(jù)平臺將為業(yè)務(wù)提供小文件合并和文件格式轉(zhuǎn)換等一鍵式數(shù)倉優(yōu)化功能。
查詢錯誤原因分析和收斂
業(yè)務(wù)在使用有數(shù)BI時會出現(xiàn)因為Impala側(cè)查詢錯誤導(dǎo)致取數(shù)結(jié)果或BI報告無法生成,嚴(yán)重影響有數(shù)產(chǎn)品的體驗。業(yè)務(wù)反饋每天會有些查詢出錯,但不知道為什么出錯,前端呈現(xiàn)的錯誤日志可讀性差,因此也不知道該如何進行改進/優(yōu)化。
1.錯誤分類
我們根據(jù)basic_info表的state字段獲取出錯(exception)的查詢,并結(jié)合detail_info表的status逐步整理出了不同原因?qū)е碌腻e誤。下面列舉出現(xiàn)較多的錯誤。
SQL自身錯誤
主要是SQL語法、參數(shù)限制和UDF誤用等,舉例如下:
org.apache.impala.common.AnalysisException: aggregate function not allowed in WHERE clause ...org.apache.impala.common.AnalysisException: Exceeded the maximum number of child expressions (10000). ...org.apache.impala.common.AnalysisException: No matching function with signature: default.dcount(BIGINT)
元數(shù)據(jù)錯誤
主要包括無法打開文件、列類型不兼容、Parquet格式不兼容、列未找到等,舉例如下:
Disk I/O error on xxx.jd.163.org:22000: Failed to open HDFS file hdfs://hz-cluster11/user/da_music/hive/warehouse/xxx Error(2): No such file or directory ...Error: File 'hdfs://hz-cluster11/user/da_music/hive/warehouse/xxx' has an incompatible Parquet schema for column 'xxx'. Column type: STRING, Parquet schema: ...org.apache.impala.common.AnalysisException: Could not resolve column/field reference: 't2.current_card' ...org.apache.impala.common.AnalysisException: Failed to load metadata for table: xxx
系統(tǒng)負(fù)載類錯誤
主要包括隊列滿、隊列超時、SQL內(nèi)存超值、進程內(nèi)存超值等錯誤。
Rejected query from pool root.default: queue full, limit=160, numqueued=165 ...Admission for query exceeded timeout 300000ms in pool root.default. Queued reason: queue is not empty (size 51); queued queries are executed first ...Memory limit exceeded: Failed to allocate row batch EXCHANGENODE (id=31) could not allocate 16.00 KB without exceeding limit. ...Failed to increase reservation by 68.00 MB because it would exceed the applicable reservation limit for the "Process"
查詢被取消
錯誤提示很簡單,有Cancelled、Session closed兩種。均是產(chǎn)品側(cè)主動kill了對應(yīng)的Impala查詢導(dǎo)致,可能原因有很多,我們目前主要關(guān)注因為執(zhí)行時間超過閾值的查詢,如音樂用的有數(shù)產(chǎn)品設(shè)置的閾值為10分鐘,這些超時查詢作為慢查詢進行分析。
2.錯誤收斂優(yōu)化
對于SQL自身錯誤,與上文所述SQL查詢性能優(yōu)化一樣,主要與有數(shù)團隊一起梳理對應(yīng)的錯誤原因,改寫有數(shù)SQL生成規(guī)則。
元數(shù)據(jù)錯誤
對于元數(shù)據(jù)錯誤,基本上是由于Impala元數(shù)據(jù)同步問題導(dǎo)致,舉云音樂的有數(shù)EasyFetch集群為例。該集群在優(yōu)化前存在較多因元數(shù)據(jù)同步導(dǎo)致的查詢錯誤,以前的同學(xué)已初步定位到是由于Impala未同步通過“Impala同步”選項開啟的表元數(shù)據(jù),但并沒有繼續(xù)分析為什么會無法同步。

在本次優(yōu)化期間,我們從頭梳理了一遍“Impala同步”選項的功能和實現(xiàn)邏輯,確定是平臺組件的代碼bug導(dǎo)致,修復(fù)后此類錯誤大幅減少。
系統(tǒng)負(fù)載類錯誤
這是個綜合性的問題,典型的場景是因為少數(shù)慢查詢長期占用了系統(tǒng)資源。對于隊列滿、隊列超時等錯誤,可以通過增加查詢的并發(fā)數(shù)或排隊超時時間來緩解,但提高查詢并發(fā)數(shù)有可能會導(dǎo)致集群過載,查詢性能進一步下降,反過來又會延長正在排隊的查詢的等待時間。另外一種可行的方式是直接向用戶提示“當(dāng)前系統(tǒng)負(fù)載過高,稍后再試”,避免用戶在短時間內(nèi)重復(fù)刷新頁面導(dǎo)致情況惡化。
對于SQL內(nèi)存或進程內(nèi)存超值等錯誤,一般是由于復(fù)雜的大查詢或?qū)Σ樵兯栀Y源預(yù)估不準(zhǔn)導(dǎo)致,對于前者,需要進行查詢優(yōu)化,比如減少數(shù)據(jù)掃描的范圍等。對于后者,可通過補上表的統(tǒng)計信息來提高評估的精度。
系統(tǒng)負(fù)載類一般通過優(yōu)化查詢性能來解決。當(dāng)然,如果一個集群每天都有好幾個小時集中出現(xiàn)大量系統(tǒng)負(fù)載類錯誤,那么可以考慮是由于集群可用資源不夠,應(yīng)該及時擴容。
后續(xù)優(yōu)化計劃
經(jīng)過大數(shù)據(jù)團隊及業(yè)務(wù)的共同努力,網(wǎng)易云音樂、嚴(yán)選等業(yè)務(wù)的Impala集群在查詢性能和錯誤收斂上取得了一定的成果,得到了音樂數(shù)倉團隊的認(rèn)可,達成了嚴(yán)選“雙十一”確定的性能指標(biāo)。
Impala的性能優(yōu)化仍在繼續(xù),下面簡單列舉正在做的事情。
全面替換公司內(nèi)部業(yè)務(wù)的Impala集群版本,從Impala 2.12升級到3.4版本,提供更強大的功能特性和性能表現(xiàn)。目前已完成音樂Impala集群升級;
引入Alluxio作為Impala與HDFS間的緩存層;
基于歷史查詢信息的表統(tǒng)計信息自動計算功能;
基于物化視圖(臨時表)的SQL重寫功能,通過創(chuàng)建預(yù)聚合表來優(yōu)化查詢性能;
與有數(shù)產(chǎn)品團隊合作實施有數(shù)查詢診斷項目。
