性能指標提升50%+,攜程數(shù)據(jù)報表平臺查詢效率治理實踐
作者簡介
攜程OLAP引擎開發(fā)組,專注于大數(shù)據(jù)OLAP引擎trino/starrocks的開發(fā)與大規(guī)模部署和運維。
一、背景
數(shù)據(jù)報表平臺(代稱Nova,后同)用于支持攜程內(nèi)部數(shù)據(jù)分析、數(shù)據(jù)挖掘、數(shù)據(jù)可視化等業(yè)務需求,目前每日承載數(shù)十萬Hive表AP查詢,所涉數(shù)據(jù)量達萬億級別。隨著用戶基數(shù)逐步提升,承載查詢量不斷增大,平臺查詢性能面臨挑戰(zhàn),具體表現(xiàn)如下:
1)平均響應時間延長,大查詢在業(yè)務高峰期存在阻塞現(xiàn)象,超時數(shù)量增多;
2)查詢所需時間不穩(wěn)定,性能波動較大,在業(yè)務高峰期可能出現(xiàn)響應時間突增現(xiàn)象;
3)查詢負載集群資源占用率高,CPU、內(nèi)存資源吃緊,I/O 請求排隊等待,進而導致集群穩(wěn)定性下降,時有節(jié)點宕機現(xiàn)象出現(xiàn)。
針對上述現(xiàn)象,我們從平臺自身服務、SQL路由分發(fā)組件、SQL執(zhí)行引擎等方面入手,采用了一套“全方位組合拳”對平臺的查詢性能進行治理,目標有二:
1)從用戶體驗角度:改善查詢性能,提升查詢效率和穩(wěn)定性;
2)從集群維護角度:提升集群穩(wěn)定性,增強查詢結(jié)果復用能力,提高算力使用效率。
二、平臺設計概覽
數(shù)據(jù)報表平臺執(zhí)行查詢的主要鏈路如圖1所示,其中有幾個關(guān)鍵構(gòu)件:
圖1:Nova 數(shù)據(jù)查詢鏈路
1)Nova:應用本體,提供可視化用戶界面,包含報表即時查詢、執(zhí)行離線定時任務等功能;
2)Router:用于分離指向不同引擎的查詢請求,起到SQL路由功能;
3)Starrocks & Hive:平臺使用Starrocks作為主要查詢引擎,向Hive外表發(fā)起查詢請求。
三、多維度數(shù)據(jù)緩存
在硬件資源有限的情況下,要提升查詢性能,最直觀的思想是對重復的查詢進行結(jié)果復用。在對平臺的查詢請求數(shù)據(jù)進行統(tǒng)計分析后,可發(fā)現(xiàn)存在相當數(shù)量的查詢請求在不同時段內(nèi)重復出現(xiàn),這為我們引入緩存機制提供了實踐基礎。
若將在執(zhí)行過程中可能遭遇瓶頸的查詢進行劃分,可將大致分為I/O型、計算型和高頻型三類,其中I/O型查詢對網(wǎng)絡和磁盤帶寬的要求較高,往往涉及大規(guī)模數(shù)據(jù)的掃描;計算型查詢對CPU和內(nèi)存資源的要求較高,往往涉及大量連接、分組、聚合、篩選、再計算操作;高頻型查詢的單次調(diào)用開銷可能較小,但在單位時間內(nèi)發(fā)起的次數(shù)顯著高于均值,在涉及遠程調(diào)用(如元數(shù)據(jù)獲?。┑沫h(huán)節(jié)可能遭遇性能瓶頸,且在單位時間造成的資源開銷可能與大查詢相當。
圖2:受限查詢分類
目前,在整個數(shù)據(jù)查詢鏈路中,我們在以下幾個環(huán)節(jié)引入了緩存機制,以應對不同類型查詢所帶來的挑戰(zhàn)。
3.1 底表Data Cache預熱
當Starrocks從Hive外表進行數(shù)據(jù)查詢時,Scan算子會將所需數(shù)據(jù)文件以塊的形式讀取至本地。對于典型的I/O型查詢而言,這個過程所需時間可達整個查詢流程耗時的70%以上。在業(yè)務高峰期,由于大量查詢請求同時發(fā)起,I/O型查詢的堆積將導致其他查詢請求讀取數(shù)據(jù)文件的等待時間增長,進而影響查詢響應時間。
針對這類情況,我們在Starrocks集群中開啟了Data Cache,將每次讀取得到的文件塊標識并臨時存儲在本地磁盤中,在下次查詢請求需要相同文件塊時,若發(fā)現(xiàn)該文件塊沒有更新,則直接從本地磁盤讀取,避免了經(jīng)由網(wǎng)絡和Hive帶來的文件讀取延遲。
通過Data Cache緩存的文件塊在Starrocks中由帶冷熱分區(qū)的LRU隊列維護,當隊列滿時,將根據(jù)文件塊的訪問頻率和時間戳進行淘汰,以保證緩存的命中率。
從緩存一致性角度,Starrocks在使用Data Cache時,會通過元數(shù)據(jù)判斷底表數(shù)據(jù)是否發(fā)生更新,若發(fā)現(xiàn)數(shù)據(jù)文件已更新,則將廢棄緩存數(shù)據(jù),重新拉取底表數(shù)據(jù)文件,以保證查詢結(jié)果的準確性。
3.1.1 預熱機制
通過對查詢請求命中底表的情況進行統(tǒng)計,可發(fā)現(xiàn)其中熱點表的使用呈現(xiàn)一定的規(guī)律性(如:每日相近時刻、每周固定幾日訪問量達峰等)。為此,我們?yōu)榻y(tǒng)計得到的各熱點表建立了用戶畫像,記錄并預測其訪問高峰。
圖3:預熱機制
通過在業(yè)務高峰到來前將熱點表數(shù)據(jù)主動Cache預熱,可進一步分散業(yè)務高峰期的I/O壓力。如圖4 所示,這部分主動指定Cache的數(shù)據(jù)文件將會優(yōu)先被置入LRU隊列的熱區(qū),以保證其在高峰期的查詢中能夠被快速命中。
圖4:Data Cache LRU 隊列
3.2 HDFS元數(shù)據(jù)緩存
在Starrocks查詢引擎執(zhí)行查詢時,需要獲取Hive表的元數(shù)據(jù)信息,如表的列信息、分區(qū)信息、表的存儲格式;HDFS File的元數(shù)據(jù)信息,如block塊屬性等。Starrocks將通過這些信息來生成最優(yōu)的執(zhí)行計劃。在業(yè)務高峰期,大量并發(fā)查詢可能導致Hadoop Namenode的元數(shù)據(jù)請求壓力過大,進而影響查詢的執(zhí)行效率。
Starrocks原有的元數(shù)據(jù)緩存時間較短,這是因為其無法實時感知HDFS File文件變化。為防止緩存不一致,原有的Remote File元數(shù)據(jù)緩存時間不宜設置過長,但這會導致即使元數(shù)據(jù)未更新,在某些場景下Starrocks也會頻繁發(fā)起重復的元數(shù)據(jù)請求。
為此,我們選擇在Starrocks的FE側(cè)通過元數(shù)據(jù)接口(該接口調(diào)用開銷遠小于元數(shù)據(jù)的獲?。υ獢?shù)據(jù)的新鮮度進行檢測,僅在遠端元數(shù)據(jù)發(fā)生更新時拉取元數(shù)據(jù),此功能可使得Remote File緩存時長延長至6小時,在保證緩存一致性的同時,提升相同元數(shù)據(jù)的復用程度。
3.3 Router Redis 緩存
當數(shù)據(jù)從查詢引擎返回至Router時,Router會將查詢結(jié)果進行緩存,以便后續(xù)面對完全相同的查詢請求,可直接從緩存中獲取結(jié)果,避免重復計算。
在緩存一致性方面,Router同樣可通過血緣信息實時獲取底表數(shù)據(jù)的更新時間,從而判斷緩存數(shù)據(jù)是否過期。在緩存數(shù)據(jù)過期時,Router將棄用緩存數(shù)據(jù),重新執(zhí)行查詢,以保證查詢結(jié)果的準確性。
3.4 Download 緩存
對于查得的報表數(shù)據(jù),平臺支持用戶將數(shù)據(jù)下載至本地,以便用戶進一步分析。在實踐過程中我們發(fā)現(xiàn),部分報表數(shù)據(jù)除了在查詢后被即時下載外,還可能需要在未來的某個時間點被再次下載(如瀏覽器關(guān)閉后)。這種行為將觸發(fā)二次查詢,導致相同請求被反復執(zhí)行以滿足下載需求。
針對這種現(xiàn)象,我們在Download服務中同樣引入了緩存機制,將下載的數(shù)據(jù)進行緩存,以便后續(xù)相同的下載請求直接從緩存中獲取數(shù)據(jù)。
圖5:Download 緩存
3.5 小結(jié)
如圖6所示,通過引入多維度數(shù)據(jù)緩存機制,我們在平臺的數(shù)據(jù)傳輸?shù)娜溌分?,盡可能實現(xiàn)了對重復數(shù)據(jù)的復用。而為了進一步提升在計算過程中,數(shù)據(jù)和算力的使用效率,我們進一步在物化視圖的使用上進行了探索。
圖6:查詢鏈路緩存總覽
四、使用物化視圖加速查詢
物化視圖(Materialized View, MV)作為一種預先計算的結(jié)果集,可以有效減少查詢時的計算量,提升查詢性能。面對計算型查詢,MV可以將查詢計算的部分結(jié)果進行固化存儲,避免復雜計算邏輯的重復執(zhí)行;面對I/O型查詢,MV可以將查詢所需數(shù)據(jù)進行預聚合,減少數(shù)據(jù)掃描的規(guī)模,或者更簡單地,將需要頻繁查詢的數(shù)據(jù)底表保存為MV,作為優(yōu)先級更高的Data Cache來使用,使得對Hive外表的查詢達到和Starrocks內(nèi)表一致的查詢性能。不過,想要發(fā)揮MV的優(yōu)勢,需要解決如下幾個問題:
1)視圖定義:如何創(chuàng)建有效的MV;
2)視圖利用:如何在查詢時高效地利用MV;
3)視圖維護:如何保證MV的新鮮度。
4.1 視圖定義:為數(shù)據(jù)集構(gòu)建MV
在Nova平臺構(gòu)建數(shù)據(jù)報表時,用戶首先需要創(chuàng)建數(shù)據(jù)集,最終在數(shù)據(jù)集定義的范圍內(nèi)進行數(shù)據(jù)查詢、生成可視化報表。這一特點使得在選擇MV的目標時,將數(shù)據(jù)集作為構(gòu)建對象是一個較為合適的選擇,因為它代表著一系列特定業(yè)務邏輯的公共數(shù)據(jù)查詢需求。
在用戶自定義的數(shù)據(jù)集中,視構(gòu)建MV的難度,可將數(shù)據(jù)集分為以下三類:
1)靜態(tài)數(shù)據(jù)集:數(shù)據(jù)集的定義不隨使用時間、用戶及其他環(huán)境因素發(fā)生變化,在底表數(shù)據(jù)不發(fā)生變化的前提下,執(zhí)行任意次查詢都將返回相同結(jié)果。此類數(shù)據(jù)集在構(gòu)建一次MV后便無需再次修改視圖定義;
2)半靜態(tài)數(shù)據(jù)集:數(shù)據(jù)集的定義按日(或更長的時間單位)進行更新,但其可變部分僅限于日期(配置了日期變參)。面對此種類型的數(shù)據(jù)集,需要構(gòu)建模板,按日重新渲染視圖;
3)動態(tài)數(shù)據(jù)集:即使數(shù)據(jù)集所涉底表的數(shù)據(jù)未有更新,但隨查詢的執(zhí)行時間不同(如包含CURRENT_TIMESTAMP函數(shù)或RAND函數(shù)等)、執(zhí)行查詢的用戶不同(數(shù)據(jù)集配置了用戶變參)、查詢的上下文參數(shù)不同(數(shù)據(jù)集配置了自定義變量)等,查詢結(jié)果也會發(fā)生變化。此類數(shù)據(jù)集的MV構(gòu)建較為困難,需要進一步拆解數(shù)據(jù)集的定義,分離得到其中靜態(tài)的部分以構(gòu)建MV,其極端情況為僅對數(shù)據(jù)集的底表進行物化。
通過將半靜態(tài)或動態(tài)數(shù)據(jù)集轉(zhuǎn)換為靜態(tài)形式,并對靜態(tài)數(shù)據(jù)集構(gòu)建MV,可將各類查詢的中間計算結(jié)果進行固化,在確保MV所涉數(shù)據(jù)底表中的數(shù)據(jù)沒有更新的前提下,可將MV中的數(shù)據(jù)進行重復利用。
4.2 視圖利用:MV自動改寫
面對一個潛在的可利用已有MV數(shù)據(jù)的查詢,Starrocks提供MV自動改寫的能力,可將查詢計劃中的相關(guān)計算邏輯改寫為直接從MV進行讀取,從而減少查詢的計算量。
Starrocks提供兩類視圖改寫規(guī)則:SPJG改寫和文本匹配改寫。
4.2.1 SPJG模式改寫
SPJG模式改寫是一種基于邏輯計劃的改寫規(guī)則,其原理基于這篇論文:《Optimizing Queries Using Materialized Views: A Practical, Scalable Solution》。
這種改寫規(guī)則的核心思想在于:首先確保查詢(或某一邏輯子樹構(gòu)成的查詢)所需的全部數(shù)據(jù)均可由MV查詢得到,隨后計算查詢與MV間的謂詞差異(稱為補償謂詞),應用至可用于改寫的視圖上,構(gòu)成一個新的查詢計劃。圖7 是改寫規(guī)則生效的一個示例。
圖7:SPJG模式改寫示例
SPJG模式改寫的優(yōu)勢在于,面對建立在相同數(shù)據(jù)集上的各類不同查詢,Starrocks可根據(jù)實際情況靈活復用已經(jīng)在MV中完成預計算的數(shù)據(jù),從而達成“一次計算,多次使用”的目的。
不過,由于這種改寫的復雜性,目前僅支持對只包含Select、Project、Join和Group-By這四類算子(SPJG)的查詢計劃樹(或邏輯子樹)進行改寫,而在涉及Union、Order-By、Limit等算子的查詢改寫時能力受限。面對復雜的數(shù)據(jù)集,更具實踐性的做法是抽取出其中的SPJG模式子樹用于創(chuàng)建MV,以擴展MV的適用范圍,增大匹配改寫成功率。
4.2.2 文本匹配改寫
文本匹配改寫是一種基于抽象語法樹(AST)的改寫規(guī)則,通過比對Query和MV規(guī)范化后的AST是否一致,可判斷是否可以將查詢改寫至MV上。
這種改寫的優(yōu)勢在于可支持更多類型算子的查詢改寫,但其改寫的自由度和適應性不如SPJG模式改寫,一旦數(shù)據(jù)集或查詢的SQL結(jié)構(gòu)在處理過程中發(fā)生變化,則文本匹配改寫可能無法發(fā)揮作用。
4.2.3 改寫數(shù)據(jù)一致性
通過合理利用上述兩類MV改寫規(guī)則,可做到以用戶無感的方式,自動復用中間計算結(jié)果,在節(jié)約計算資源的同時大幅提升復雜查詢的效率。
值得一提的是,在數(shù)據(jù)一致性方面,Starrocks在執(zhí)行查詢改寫流程時,會自動檢測MV中的數(shù)據(jù)是否過期,若是,則放棄改寫,執(zhí)行原有查詢計劃。這使得引入MV查詢改寫機制后,在達成查詢加速效果的同時,依然能夠保證查詢結(jié)果的準確性。
而由于此機制的存在,截至目前,Starrocks在執(zhí)行MV改寫時,若發(fā)現(xiàn)MV本身的定義中包含非確定返回值(Non-deterministic)函數(shù),例如CURRENT_DATE 和 RAND等,將棄用此MV,這是因為Starrocks無法保證MV返回的結(jié)果在當前時刻下依然可用。因此,在選擇數(shù)據(jù)集進行物化時,必須先確保數(shù)據(jù)集的定義為靜態(tài),這也是“視圖定義”小節(jié)對數(shù)據(jù)集分類的重要意義所在。
4.2.4 CURRENT_DATE函數(shù)改寫問題
在構(gòu)建MV時,我們發(fā)現(xiàn)部分數(shù)據(jù)集的定義中包含CURRENT_DATE函數(shù),而并未使用平臺提供的日期變參($EFFECTDATE)。這將導致即使數(shù)據(jù)集SQL的文本定義未發(fā)生變化,隨著時間推進,數(shù)據(jù)集本身所指代的數(shù)據(jù)范圍卻按日發(fā)生變化。
與平臺提供的日期變參不同的是,CURRENT_DATE函數(shù)在執(zhí)行時不會被替換為具體日期,而是在查詢時由執(zhí)行引擎動態(tài)計算,這使得查詢引擎在執(zhí)行改寫操作時,將由于涉及非確定返回值函數(shù)而棄用此類數(shù)據(jù)集對應的MV,使得這類本該滿足半靜態(tài)數(shù)據(jù)集條件的數(shù)據(jù)集需要被作為動態(tài)數(shù)據(jù)集處理。
經(jīng)統(tǒng)計,報表平臺中目前有相當數(shù)量的數(shù)據(jù)集定義,其可變部分僅為CURRENT_ DATE函數(shù),為提升對此類數(shù)據(jù)集的物化能力,我們在平臺側(cè)引入了重渲機制,在將查詢請求提交至引擎前,會將CURRENT_DATE函數(shù)以和EFFECTDATE變參類似的方式重渲為具體日期,從而保證查詢引擎的改寫機制能夠正常生效。
4.3 視圖維護:MV自動刷新
在確保MV SQL為靜態(tài)的前提下,MV的數(shù)據(jù)新鮮度僅和底表數(shù)據(jù)是否更新有關(guān)。通過分析MV創(chuàng)建語句中SQL所涉及的底表追溯血緣依賴關(guān)系,并通過元數(shù)據(jù)服務獲取底表的最近更新時間,可創(chuàng)建自動化應用實時監(jiān)控MV是否過期,并根據(jù)實際情況選擇是否刷新MV。
4.4 MV價值發(fā)掘
為數(shù)據(jù)集創(chuàng)建MV并不一定必然為平臺的查詢性能帶來優(yōu)化,原因可羅列為以下幾點:
1)MV的創(chuàng)建和維護需要消耗額外的計算資源,每一次刷新都對應一次對數(shù)據(jù)集的查詢操作。若MV的使用率較低,其帶來的性能提升可能無法彌補其維護成本;
2)部分數(shù)據(jù)集在定義時所涉及的數(shù)據(jù)范圍遠大于真正使用所需,在直接執(zhí)行查詢操作時,可通過謂詞下推等優(yōu)化操作過濾掉不必要的掃描范圍,而如果為此類數(shù)據(jù)集創(chuàng)建MV,將反而導致更大的全局計算開銷;
3)Starrocks集群能夠提供的磁盤空間有限,不可能為所有數(shù)據(jù)集都創(chuàng)建MV來優(yōu)化。在有限的資源下,需保證“好鋼用在刀刃上”,優(yōu)先創(chuàng)建有較大查詢性能提升潛力的MV進行創(chuàng)建。
為此,我們在MV的選擇過程中,引入了MV價值評估機制,通過綜合分析數(shù)據(jù)集的使用頻率、數(shù)據(jù)集計算及相關(guān)查詢的計算代價、數(shù)據(jù)集的數(shù)據(jù)規(guī)模等多個維度,為數(shù)據(jù)集的MV創(chuàng)建提供參考。以查詢所消耗的CPU代價為例,建立MV前后的所節(jié)省的計算代價可使用如下公式計算:
為精確捕獲查詢執(zhí)行或數(shù)據(jù)集刷新的計算代價,我們會將統(tǒng)計得到的待改寫查詢(高代價或高頻查詢)在獨立環(huán)境下執(zhí)行預跑,獲取量化數(shù)據(jù)作為評估的依據(jù),大致測試流程如圖8所示。
圖8:MV價值評估流程
4.5 小結(jié)
通過選取合適的數(shù)據(jù)集構(gòu)建MV,并利用Starrocks的自動改寫能力加速查詢,可在一定程度上規(guī)避平臺在計算過程中的出現(xiàn)的短板,補足全查詢鏈路的數(shù)據(jù)復用能力,使得數(shù)據(jù)報表平臺面對不同類型的高負載查詢,有更加成熟、可靠、易維護的應對方案。
五、查詢策略優(yōu)化和SQL質(zhì)量治理
目前,數(shù)據(jù)報表平臺所承載的查詢?nèi)蝿罩饕譃閮深悾阂皇羌磿r報表查詢,用戶通過Web界面即時運行查詢并獲取數(shù)據(jù)報表;二是離線定時任務調(diào)度,用戶通過配置定時任務執(zhí)行查詢,任務觸發(fā)后用戶可通過郵件等途徑獲取數(shù)據(jù)。
這兩類查詢?nèi)蝿辗謩e存在以下特征:
1)即時報表查詢:觸發(fā)時間隨機,由用戶自主觸發(fā),查詢請求所涉計算量相對較小,但對查詢響應時間更為敏感,一般要求在數(shù)秒內(nèi)返回結(jié)果;
2)離線定時任務調(diào)度:觸發(fā)時間固定,由預注冊的計劃周期性自動觸發(fā),查詢需要計算的數(shù)據(jù)量往往較大,但對查詢響應時間要求相對較低,一般可容忍的查詢響應延遲較寬。
立足于平臺自身的業(yè)務場景思考,可發(fā)現(xiàn)以下痛點:
1)負載不均問題:平臺執(zhí)行查詢的高峰和低谷期分明,需要調(diào)整定時任務調(diào)度策略,以平滑負載;
2)資源爭用問題:相同時間段內(nèi),不同查詢間存在資源爭用,例如離線定時任務的執(zhí)行可能影響同期即時報表查詢的性能;
3)慢查詢問題:部分查詢請求自身所需的計算資源過大,或是配置的計算邏輯不佳,可能對平臺造成過量負載。
對于慢查詢問題,其成因可能有多種,包括但不限于以下幾點:
1)平臺查詢策略問題:面對特定查詢,原有的實現(xiàn)或查詢策略在執(zhí)行時性能較差,需要進行改進;
2)查詢SQL實現(xiàn)欠優(yōu):查詢SQL在實現(xiàn)上存在質(zhì)量問題,在執(zhí)行時消耗的計算量遠大于業(yè)務邏輯所需,可能引入大量非必要的底表掃描和計算操作,需要整治優(yōu)化;
3)業(yè)務需求:即使優(yōu)化了查詢策略和SQL質(zhì)量,仍有部分查詢請求所需計算量較大,對于其中涉及關(guān)鍵業(yè)務的部分,可能需要整合計算資源,以專門提升這類查詢的性能。
在本節(jié)中,將分別對目前我們針對上述痛點所做的工作進行闡述。
5.1 整點調(diào)度問題治理
Nova平臺所提供的離線任務定時調(diào)度功能,由用戶根據(jù)所需自行配置任務的觸發(fā)時間。但出于用戶習慣,可發(fā)現(xiàn)大量查詢都被設置在整點進行調(diào)度,這導致平臺在整點出現(xiàn)查詢負載高峰。
通過對此業(yè)務場景的痛點進行分析,我們采用了兩種策略來解決整點調(diào)度問題。
一方面,通過與用戶溝通,我們提出了“錯峰調(diào)度”策略,即在原有配置的基礎上,對部分任務進行時間錯峰調(diào)度,以減少整點負載高峰。例如,原定于每日九點執(zhí)行的調(diào)度任務,可能被延遲至九點十分執(zhí)行。這種策略在一定程度上緩解了整點負載高峰的問題,而不至于為用戶帶來過多的使用不便。
另一方面,我們提供了“依賴調(diào)度”方案,即不再以時間,而是以數(shù)據(jù)更新為觸發(fā)條件進行調(diào)度。報表元數(shù)據(jù)完成更新時間的隨機性,使得這種調(diào)度方式可變相地起到“錯峰調(diào)度”的作用,且通過數(shù)據(jù)更新作為觸發(fā)條件,可使得報表數(shù)據(jù)新鮮度具有更加便捷的維護方式。
5.2 查詢流量切分
資源隔離是避免查詢請求相互干擾的有效手段。通過將平臺的查詢請求按照類型進行切分,能夠有效提升查詢請求的執(zhí)行效率。
平臺的原有的查詢請求路由策略僅根據(jù)用戶指定的查詢引擎類型進行請求分流,而根據(jù)即時報表查詢和離線調(diào)度查詢的特征,我們選擇進一步改進路由策略,將這兩類查詢請求分發(fā)至不同的Starrocks集群,防止離線調(diào)度過高的查詢負載對即時報表查詢的響應時間造成影響。
另外,通過對平臺每日查詢性能數(shù)據(jù)進行分析,可識別得到一系列慢查詢請求,這些SQL需要我們根據(jù)實際情況細分,并逐步對其進行優(yōu)化。為避免這些查詢請求對平臺中其他查詢的性能造成影響,我們選擇將這類查詢分發(fā)至專門用于處理待優(yōu)化查詢的獨立Starrocks集群,以減輕對主集群的壓力。
圖9:查詢流量切分
5.3 Max-d查詢專項治理
在各類數(shù)據(jù)集的查詢中,有一類典型的SQL在實際查詢時將引入極高的查詢代價。這類查詢在對數(shù)據(jù)條目的日期d進行篩選時,使用max(d)子查詢作為謂詞判斷依據(jù),以獲取數(shù)據(jù)集中所包含的最新一日的數(shù)據(jù)進行計算,SQL示例如下所示:
此種查詢結(jié)構(gòu)將導致查詢引擎在實際執(zhí)行查詢時,對數(shù)據(jù)表的每一行數(shù)據(jù)都觸發(fā)一次全表掃描的子查詢調(diào)用,隨著數(shù)據(jù)表數(shù)據(jù)量的上升,這種查詢的查詢代價將呈二次函數(shù)倍率增長,產(chǎn)生難以忽視的性能開銷。
面對這類查詢,我們對其執(zhí)行策略分兩期進行了專項優(yōu)化。
第一期,在Router側(cè),通過對查詢SQL的AST進行模式匹配,可篩得存在Max-d問題的查詢請求。在此基礎上,我們將這類查詢的執(zhí)行策略拆分為兩階段:首先執(zhí)行max(d)子查詢,獲取最新日期d的值,隨后將此實值作為謂詞條件對原查詢進行改寫后執(zhí)行。
通過這種方式,不但可解決原有的嵌套查詢問題,將查詢掃表的時間復雜度由O(N2)降至O(N),還可進一步觸發(fā)Starrocks的列分區(qū)裁剪行為,大幅減少這類查詢的計算代價。
第二期,在Nova平臺側(cè),直接通過配置變參方式替換Max-d SQL,然后獲取MetaStore元數(shù)據(jù)最新分區(qū)替換變量。此舉可提升這種執(zhí)行機制的可維護性,且max(d)值在計算前即可獲取,能夠進一步提升優(yōu)化后的查詢性能。
5.4 SQL實現(xiàn)優(yōu)化
查詢效率優(yōu)化的核心在于提升查詢的執(zhí)行速度、降低資源消耗,然而單從查詢的執(zhí)行側(cè)進行優(yōu)化,對于存在潛在質(zhì)量問題的SQL,仍然難以解決根本病因。通過分析歸納用戶提交的SQL中可能導致查詢效率低下的原因,我們與用戶協(xié)調(diào),開展了以下幾類SQL語句優(yōu)化工作。
5.4.1 distinct * 語句刪減
在撰寫SQL時,為保證查詢結(jié)果的唯一性,用戶可能會習慣性地添加distinct * 子句進行去重,然而這種操作涉及到全表數(shù)據(jù)行、全字段域的掃描去重,當目標數(shù)據(jù)集合行數(shù)或列數(shù)較多時,將產(chǎn)生大量的cpu和內(nèi)存資源開銷。
為減少這類查詢的資源消耗,我們向用戶提出了兩項修改建議:
1)檢查在使用distinct * 前,計算結(jié)果是否已由上游數(shù)據(jù)源或計算操作去重,避免重復引入去重操作;
2)檢查當前去重操作是否必要,是否必須對全部字段進行去重,盡可能減少對去重操作的依賴。
5.4.2 數(shù)據(jù)表拆分
通過對部分復雜的查詢邏輯進行分析,可發(fā)現(xiàn)其主要原因是數(shù)據(jù)模型設計不合理,對應的數(shù)據(jù)表拆分不當,例如一些權(quán)限表和靜態(tài)信息表存在嚴重耦合,致使計算邏輯復雜,查詢數(shù)據(jù)量大。
對于這類問題,重新設計底表數(shù)據(jù)模型,將非必要的耦合部分進行子表拆分,重新定義數(shù)據(jù)集和報表計算流程,往往可以起到理想的性能優(yōu)化效果。
5.4.3 限制查詢分區(qū)
部分用戶在創(chuàng)建SQL(主要是定義數(shù)據(jù)集)時,未對數(shù)據(jù)查詢范圍進行限制,或所做限制缺乏發(fā)展性考慮。例如,對一個按日分區(qū)的數(shù)據(jù)表,簡單地將數(shù)據(jù)表查詢范圍設置為 d > 2022-01-01,而未配置動態(tài)參數(shù)。隨著時間積累,此類數(shù)據(jù)集的查詢資源開銷將逐步上升,出現(xiàn)查詢性能劣化現(xiàn)象。
在一個SQL被執(zhí)行時,所涉底表分區(qū)的數(shù)量可能會對查詢性能產(chǎn)生重要影響,因為它對應著查詢涉及的目標點位數(shù)量。為提升此類數(shù)據(jù)集的查詢性能,我們向用戶提出了限制查詢分區(qū)的建議,例如根據(jù)所需添加動態(tài)日期范圍限制,保證報表數(shù)據(jù)計算的可持續(xù)發(fā)展性。
5.5 潛在慢查詢阻斷機制
為防止未經(jīng)優(yōu)化的SQL對平臺的查詢性能造成影響,我們在平臺側(cè)引入了慢查詢阻斷機制,對用戶提交的SQL進行檢查,判斷其是否滿足執(zhí)行標準,目前主要涉及以下兩個點位:
1)平臺規(guī)范卡點:當用戶在平臺新增或修改數(shù)據(jù)集/報表時,平臺將對用戶提交的SQL進行檢查,判斷其是否滿足規(guī)范。目前,上述規(guī)范將檢查用戶提交查詢的掃描行數(shù)、查詢耗時和占用內(nèi)存,而后續(xù)將進一步補充對Join連接數(shù)、底表個數(shù)、Union操作個數(shù)、所涉分區(qū)數(shù)等指標的檢查,以保證用戶提交的SQL質(zhì)量符合平臺的執(zhí)行標準。
2)Starrocks熔斷機制:當Starrocks為查詢請求生成執(zhí)行計劃,發(fā)現(xiàn)待掃描的文件數(shù)和分區(qū)數(shù)量過大時,將觸發(fā)熔斷機制,跳出此次查詢的執(zhí)行,并返回錯誤信息。
六、成效
通過以上一系列的查詢性能治理措施,我們在數(shù)據(jù)報表平臺的查詢性能上達成了階段性目標,平臺查詢性能逐步穩(wěn)定,具體表現(xiàn)如下:
1)查詢平均響應時間降低:在業(yè)務高峰期,平臺的查詢平均響應時間從原來的8秒降低至4秒;
2)查詢超時數(shù)量顯著降低:查詢時間90線由原先的約18秒降低至約8秒,由超時導致的查詢失敗量由日均7000次縮減至日均1400次;
3)查詢性能波動幅度減小:平臺每日平均查詢性能指標趨于平滑,全平臺查詢時間標準差由原來的約25秒縮短至14秒左右;
圖10:查詢響應時間統(tǒng)計
對平臺所承載的各類大查詢而言,本文所述的治理策略起到的優(yōu)化作用尤為明顯,由圖11可見,長耗時查詢數(shù)量在治理措施實施后呈明顯下降趨勢。
圖11:長耗時查詢數(shù)量變化趨勢
七、總結(jié)
通過本文所述內(nèi)容,我們采取了多項措施來對數(shù)據(jù)報表平臺的查詢效率進行治理。通過建立緩存機制、使用物化視圖,可提升查詢性能和算力使用效率;通過對查詢策略進行優(yōu)化,可裁剪非必要開銷,解放平臺查詢瓶頸;通過切分流量和對SQL質(zhì)量進行管控,可更好地實現(xiàn)資源隔離,提升平臺查詢質(zhì)量。
未來,隨著治理措施的不斷演進,這些優(yōu)化策略將被逐步規(guī)范化、集成化、自動化,以更好地服務于平臺的查詢需求。