前沿 | VLDB論文解讀:阿里雲超大規模實時分析型資料庫AnalyticDB
前言
一年一度的資料庫領域頂級會議VLDB 2019於美國當地時間8月26日-8月30日在洛杉磯召開。在本屆大會上,阿里雲資料庫產品團隊多篇論文入選Research Track和Industrial Track。
本文將對入圍Industrial Track的論文《AnalyticDB: Realtime OLAP Database System at Alibaba
Cloud》進行深度解讀。
1、背景
隨著資料量的快速增長,越來越多的企業迎來業務資料化時代,資料成為了最重要的生產資料和業務升級依據。伴隨著業務對海量資料實時分析的需求越來越多,資料分析技術這兩年也迎來了一些新的挑戰和變革:
1) 線上化和高可用、離線和線上的邊界越來越模糊,一切資料皆服務化、一切分析皆線上化;
2) 高併發低延時,越來越多的資料系統直接服務終端客戶,對系統的併發和處理延時提出了新的互動性挑戰;
3) 混合負載,一套實時分析系統既要支援資料加工處理,又要支援高併發低延時的互動式查詢;
4) 融合分析,隨著對資料新的使用方式探索,需要解決結構化與非結構化資料融合場景下的資料檢索和分析問題。
圖1 阿里巴巴分析型資料庫發展歷史
阿里巴巴最初通過單節點Oracle進行準實時分析, 後來轉到Oracle RAC。隨著業務的飛速發展, 集中式的Shared Storage架構需要快速轉向分散式,遷移到了Greenplum,但不到一年時間便遇到擴充套件性和併發的嚴重瓶頸。為了迎接更大資料集、更高併發、更高可用、更實時的資料應用發展趨勢,從2011年開始,線上分析這個技術領域,阿里實時資料庫堅定的走上了自研之路。大規模、海量資料實時分析型資料庫系統——AnalyticDB,也是在這個時候誕生。
AnalyticDB是阿里巴巴自主研發、唯一經過超大規模、高併發以及核心業務驗證的PB級實時分析型資料庫。自2012年第一次在集團釋出上線以來,至今已累計迭代釋出近百個版本,支撐起集團內的電商、廣告、菜鳥、文娛、飛豬等眾多線上分析業務。AnalyticDB於2014年在阿里雲開始正式對外輸出,支撐行業既包括傳統的大中型企業和政府機構,也包括眾多的網際網路公司,覆蓋外部十幾個行業。AnalyticDB承接著阿里巴巴廣告營銷、商家資料服務、菜鳥物流、盒馬新零售等眾多核心業務的高併發分析處理,每年雙十一上述眾多實時分析業務高峰驅動著AnalyticDB不斷的架構演進和技術創新。
圖2 AnalyticDB設計挑戰
2、挑戰
已有的分析型資料庫(以下簡稱OLAP)諸如Impala、Pinot、Druid等,總結了OLAP系統在設計的過程中應該解決的問題:低延遲、資料新鮮度、多樣性、低成本、高擴充套件性、高可靠性。和這些已有的OLAP系統相比,AnalyticDB承載著更大的規模:2000+臺物理機器、10PB+規模資料、百萬張資料表以及萬億條資料行。因此,AnalyticDB在設計與實現的時候,不僅要解決已有OLAP系統要解決的問題,還要面臨與解決三個更大的挑戰:
1) 隨著使用者分析需求的急劇增加,使用者的查詢變得複雜且多樣化:這些查詢涵蓋點查詢、全表掃描、多表關聯等,還會包含對任意列組合的篩選條件。如何在這種複雜分析場景下依然保證大部分甚至所有查詢的低延遲,是一個非常大的挑戰;
2) 如何在保證低延遲查詢的情況下,仍然能處理每秒千萬級別的寫吞吐。傳統的設計理念在同一條鏈路上同時處理讀寫請求,這會造成讀寫效能的互相嚴重影響。
3) 複雜分析場景下,會對行存、列存、關係型儲存、複雜資料型別(JSON、vector、text)都有著強烈需求。如何設計一個對這些儲存格式都很友好的儲存層,也是一個業界難題。
接下來我們會介紹AnalyticDB的設計與實現關鍵點,探究AnanlyticDB是如何解決這些挑戰的。
3、 AnalyticDB架構
AnalyticDB的整體架構如下圖:
圖3 AnalyticDB架構圖
每個模組的具體描述如下:
- Coordinator(協調節點):協調節點負責接收JDBC/ODBC連線發過來的請求,並將請求分發給讀節點或者寫節點。
- Write Node(寫節點):只處理寫請求(如INSERT、DELETE、UPDATE)的節點。
- Read Node(讀節點):只處理讀請求(如SELECT)的節點。
- Pangu(盤古):高可靠分散式儲存系統,是AnalyticDB依賴的基礎模組。寫節點會將寫請求的資料刷到盤古上進行持久化。
- Fuxi(伏羲):資源管理與任務排程系統,是AnalyticDB依賴的基礎模組。伏羲合理使用叢集機器的空閒資源,以進行相關計算任務的非同步排程執行。
3.1、表分割槽
為便於大規模分析處理,AnalyticDB對資料表進行分割槽。AnalyticDB資料表有兩個分割槽級別:一級分割槽和二級分割槽。圖4展示了建立帶有一級分割槽、二級分割槽表的DDL語句:一級分割槽有50個分割槽,分割槽鍵為id列;二級分割槽有12個分割槽,分割槽鍵為dob列。資料行依據其包含的一級分割槽鍵的hash值,對應到不同的一級分割槽。通常,選擇具有較高基數(cardinality)的列作為一級分割槽鍵,以保證資料行能均勻地分佈到每個一級分割槽,最大化並行。使用者還可以根據需要定義二級分割槽,以便進行資料的自動管理。二級分割槽擁有最大分割槽數,當二級分割槽的實際數目超過了這個最大分割槽數後,最老的二級分割槽會被自動刪除。通常,選擇時間列(天、周或月)作為二級分割槽列,這樣,包含相同時間序列的資料行,會被劃分到同一個二級分割槽中。
圖4 建立帶有分割槽的資料表的DDL
3.2、讀寫分離
傳統OLAP系統在同一個鏈路上同時處理讀寫請求,因此,所有的併發讀寫請求都共享同一個資源池,也會互相影響。但是當讀寫併發同時非常大時,這種設計會由於過度的資源競爭而導致不好的效能。如圖5所示,為了解決這個問題,同時確保讀和寫的高效能,AnalyticDB採用的架構為讀寫分離架構,即AnalyticDB有獨立的讀寫節點各自處理讀寫請求,且寫節點和讀節點完全互相隔離。
圖5 AnalyticDB讀寫分離
寫節點:某個寫節點會被選為主節點,其他寫節點選為從節點,主節點和從節點之間通過ZooKeeper來進行通訊。每個節點會獨立負責某些一級分割槽的資料,主節點的任務就是決定每個節點負責哪些一級分割槽。協調節點會將寫請求分發到對應的寫節點上,寫節點收到請求後,會將寫SQL語句放到記憶體buffer中,這些buffer中的SQL語句稱為log資料。寫節點會將buffer中的log資料刷到盤古上,當刷盤古成功後,寫節點會返回一個版本號(即LSN)給協調節點,表示寫完成了。每個一級分割槽在其對應的寫節點上,都會獨立地對應一個版本號,每次寫節點將某個一級分割槽的log資料刷到盤古後,都會增大這個版本號,並將最新版本號返回給協調節點。
當盤古上的log資料達到一定規模時,AnalyticDB會在伏羲上啟動MapReduce任務,以將log資料轉換成真實儲存資料+索引。
讀節點:每個讀節點也獨立負責某些一級分割槽的資料。在每個讀節點初始化時,它會從盤古上讀取最新版本資料(包括索引)。之後,基於這份資料,讀節點會從寫節點的記憶體buffer中將寫請求log週期性地拉取過來,並在本地進行replay,replay之後的資料不會再儲存到盤古中。讀節點根據replay之後的資料,服務到來的讀請求。
由於讀節點需要去從寫節點上拉取寫請求資料,因此讀節點為使用者提供了兩種可見性級別:實時(real-time)可見和延時(bounded-staleness)可見。實時可見允許讀節點立即讀到寫節點寫入的資料,延時可見允許讀節點在一段時間後才讀到寫節點上寫入的資料。AnalyticDB預設使用的可見性級別為延時可見。
當可見性級別選擇為實時可見時,AnalyticDB採用了版本校驗(version verification)機制來確保讀寫節點的同步。當用戶執行完寫請求後,他/她再發送一個查詢請求到協調節點。協調節點會從對應寫節點上獲取最新的版本號(記為V1),連同查詢請求一起下發給對應的讀節點。讀節點上在進行本地replay的時候,也會存有目前已經replay的版本號(記為V2)。讀節點會比較V1和V2的大小:如果V1小於等於V2,那麼讀節點直接基於本地replay的資料執行查詢;如果V1大於V2,那麼讀節點會從對應寫節點上拉取直到V1的log資料,replay後再執行查詢。需要強調的是,當可見性級別為延時可見時,協調節點在下發查詢請求之前,不會實時地從對應寫節點上獲取最新版本號,而是使用快取的之前寫節點返回給自己的版本號(由於存在很多協調節點,所以某個協調節點上快取的版本可能不是最新版本)。
3.3、可靠性與擴充套件性
- 可靠性。
AnalyticDB的讀節點和寫節點均具有高可靠性。對於寫節點來說,當某個從節點失效的時候,主節點會將其負責的一級分割槽均勻地分配給其他正常的從節點。當主節點失效的時候,新的主節點會被重新選出來進行替代。對於讀節點來說,使用者可以指定讀節點的副本個數(預設為2),不同副本會被放到不同的物理機上,以提供高可靠性。當某個讀節點失效時,協調節點會將讀請求自動下發到其他副本上。需要強調的是,某個寫節點的失效,也不會影響讀節點正常地拉取log資料和replay資料。因為log資料是持久化在盤古上的,在寫節點失效地時候,讀節點可以直接去盤古上拉取log資料。 - 擴充套件性。
AnalyticDB的讀節點和寫節點也具有高可擴充套件性。當一個新的寫節點加入時,主節點會自動調整一級分割槽的分配,保證負載均衡。讀節點的可擴充套件性也是由相同的機制保證的,只不過對於讀節點,調整一級分割槽分配的是協調節點。
3.4、叢集管理
AnalyticDB叢集管理模式為多租戶模式,即同一個叢集上可以執行多個AnalyticDB例項。我們設計並實現了一個稱為Gallardo的叢集管理元件,Gallardo採用CGroup技術對不同AnalyticDB例項進行資源隔離(CPU核、記憶體、網路頻寬),並負責例項的穩定性。當新的AnalyticDB例項建立的時候,Gallardo會為其分配相應的資源,在分配資源的時候,Gallardo會將協調節點、寫節點、讀節點以及讀節點的不同副本放置在不同物理機上,以保證可靠性要求。
4、 AnalyticDB儲存層設計
AnalyticDB儲存圍繞為“計算而生” 這一設計目標,主要解決海量資料的極速查詢問題。本章將詳細剖析儲存和索引原理,並闡述設計背後的思考。
4.1、儲存層架構
AnalyticDB儲存層採用Lambda架構,讀節點上的資料包括基線資料和增量資料兩部分。如圖6左邊所示,基線資料是增量寫入前的所有歷史資料,包括索引和明細資料;增量資料沒有索引,只有明細資料。明細資料來自於寫入節點的日誌資料,並按照行列混存的結構(見4.2節)儲存在讀節點的SSD磁碟上。
圖6 Lamda架構和資料查詢過程
4.1.1、寫入和查詢過程
AnalyticDB不僅支援實時INSERT,同時還支援UPDATE和DELETE。執行DELTE時,AnalyticDB沒有采用立即物理刪除,而是使用bitset來標記被刪除的資料行,這些被標記刪除的資料會在資料合併(4.1.2)時被真正物理刪除。執行UPDATE時,UPDATE操作會被轉換為DELETE + INSERT。COPY-ON-WRITE技術被用來支援MVCC多版本控制。當資料發生刪除或更新時,AnalyticDB會產生一個新版本的bitset,並將被刪除後更新的行的位設定1。此時正在執行的查詢可以繼續使用老版本的delete bitset,不會被寫入阻塞。
演算法1、2、3分別詳細解釋了INSERT、DELETE和QUERY執行的詳細過程。
4.1.2、資料合併
由於沒有全域性索引,隨著資料的不斷實時寫入,增量資料的查詢效能會越來越慢。因此我們會在後臺通過伏羲啟動一個MapReduce 任務來合併基線資料和增量資料(同時去掉標記為刪除的資料)形成一個新的基線資料,並基於新的基線資料構建全量索引。如圖7所示,當資料合併任務開始時,首先會將增量資料引擎標記為immutable,並建立一個新的活躍增量資料引擎,該活躍增量資料引擎接受實時寫入的資料。在合併任務執行過程中,所有查詢和INSERT/DELETE都會執行在基線資料、immutable增量資料和活躍增量資料這三個資料引擎上。當合並任務完成後,老的基線資料和immutable增量資料會被替換為新的基線資料,新的查詢將執行在新基線資料和活躍增量資料這兩個資料引擎上。等所有老的查詢都結束後,老基線資料和immutable增量資料會被刪除。
圖7 資料合併過程
4.2、儲存資料結構
4.2.1、行列混存
在海量資料分析場景下,資料分析業務主要有以下三類workload:
1) OLAP場景下的大規模多維分析:海量資料的統計分析和多表關聯,比較適合列存格式;
2) 高併發的點查:通常需要撈取出一整行的明細資料,比較適合行存。
3) 高寫入吞吐:每秒千萬的高吞吐實時寫入,比較適合行存。
無論是行存和列存都無法同時滿足以上需求,如何在一個系統中同時解決以上問題?如圖8所示,AnalyticDB提出使用行列混存 結構,使用一套儲存格式,兼具行存和列存之所長,同時滿足以上三類workload。
圖8 行列混存資料格式
對於一張表,每k行資料組成一個Row Group。在每個Row Group中,每列資料連續的存放在單獨的block中,Row Group在磁碟上連續存放。每個block由於資料型別相同,可以支援高效的壓縮。同時為了保證點查詢的效能,我們會將所有的資料按照按指定列(聚集列)排序存放,好處是在按該列查詢時顯著減少磁碟隨機IO次數。最後,與列存寫入相比,行列混存可以把多個檔案的寫入被轉化成單個檔案的順序寫入,降低了IO的開銷。
4.2.2、元資料
為了加速查詢,AnalyticDB對每列構建一份元資料,並儲存在一個叫detail_meta的單獨檔案中。detail_meta檔案通常較小(小於1MB),首次查詢時被載入在記憶體中。如圖8左邊所示,元資料主要包括4部分:
- Header。包括版本號,檔案長度以及一些統計資訊。
- 列統計資訊。包括行數,NULL值數,cardinality,SUM,MAX和MIN 值。優化器根據這些資訊來生成最佳執行計劃。
- 字典。對於cardinality較少(小於1024)的列,AnalyticDB採用字典編碼,資料檔案裡儲存字典號碼。字典儲存在該欄位中。
- 塊地址資訊。儲存塊號到資料檔案起始地址和長度的對映關係。
4.2.3、非結構化資料儲存
AnalyticDB不僅支援基本資料型別,也支援長文字、JSON和向量陣列等非結構化資料型別。但是單行文字、JSON、向量資料的長度通常比基本資料型別的資料要長,單行長達數十KB甚至MB級別。基於固定行數的block設計會導致單個block過大,IO效率降低。因此針對非結構化資料型別,AnalyticDB採用了定長資料塊技術,每個塊大小相同。
如圖9所示,每個Block由多個定長資料塊(稱作FBlock)組成,每個FBlock大小為32KB,單獨儲存為一個檔案中。Block中儲存的不再是原始資料內容,而是資料所在FBlock的塊號和FBlock內的偏移位置。查詢時,首先讀取Block中的內容,得到FBlock的塊號和塊內偏移,然後再讀取FBlock內容,得到非結構化資料內容。
圖9 定長資料塊格式
4.3、索引管理
索引是資料庫系統裡影響效能最關鍵元件,但是傳統的索引並不能很好滿足OLAP場景下任意ad-hoc查詢的需求。例如B+Tree索引,在海量資料下存在中間節點過多,容易產生大量隨機IO等問題;Druid可以對多列資料構建倒排索引,但是隻能支援特定資料型別(字串型別,不支援數值型別); 傳統資料庫構建索引佔用大量資源,影響寫入效能;現有的索引也不支援非結構化資料型別,例如JSON,長文字和向量。
因此,AnalyticDB設計和實現了一個新的索引引擎,在不影響寫入效能的情況下,支援結構化和非結構化資料型別索引。它將構建過程從寫入鏈路中移除,採用後臺非同步構建模式,支援對所有列構建索引,從而解決了OLAP任意查詢的效能問題。
4.3.1、索引查詢
AnalyticDB預設對所有列構建索引,並儲存在一個單獨的檔案中。與傳統的資料庫不同,AnalyticDB索引中的key是列的值,value是該值出現的所有行號集合,並支援所有的條件同時走索引查詢。如圖10所示,該SQL是一個複雜查詢包括結構化列條件和非結構化列條件。索引引擎會首先對每個條件走索引掃描,得到多個行號集合,然後將AND/OR 條件轉換為行號集合的UNION/INTESECT操作。
圖10 索引查詢示例
AnalyticDB在索引引擎是實現上也做了大量的優化,包括:多路流式歸併、索引選擇CBO和索引結果快取。
多路流式歸併:傳統資料庫大多采用2路歸併策略,在條件數特別多的場景下,會導致大量中間結果,計算效率很低。AanlyticDB採用K路流式歸併演算法,可以支援多個集合並行歸併,避免產生大量中間結果集合,提升了整個歸併的速度。
索引選擇CBO:當where條件中包括多個條件,並不是所有的條件走索引掃描能取得最佳的效能。利用索引中的統計資訊,提前估算出各個條件可能的選擇率,對於選擇率很高的條件走索引查詢,其他條件直接在上層進行過濾操作。例如對於where id = 1 and 0 < x < 1000000的情況下,d = 1這個條件的選擇率已經很高,則0索引結果快取:在OLAP分析場景中,多個查詢條件中,可能會出現部分條件固定不變或重複多次出現。針對這種場景AnalyticDB 實現了一個高效的無鎖快取,快取的的key為等值或range條件,value為行號集合。這樣在出現重複查詢情況下,可以直接讀取快取,避免索引IO掃描開銷。
4.3.2、索引構建
為了支援每秒千萬的實時資料寫入,避免同步構建索引影響實時寫入的效能,AnalyticDB並沒有採用同步構建索引的策略,而是採用非同步後臺程序構建索引的方式。索引引擎會根據時間或增量資料的大小來決定是否啟動後臺程序來構建索引。該後臺程序讀取Pangu上的歷史全量資料和新寫入的增量日誌資料,完成資料合併形成新的全量資料,並對該全量資料重新構建索引。該過程通過伏羲的MapReduce任務執行,選擇負載較低的機器執行,對使用者完全透明。
5、 AnalyticDB計算層設計
5.1、優化器
AnalyticDB綜合了CBO(基於代價估算)和RBO(基於規則)的優化模型來為實時線上分析提供最優的計劃。優化規則的豐富程度是能否產生最優計劃的一個重要指標。因為只有可選方案足夠多時,才有可能選到最優的執行計劃。AnalyticDB提供了豐富的關係代數轉換規則,用來確保不會遺漏最優計劃。
- 基礎優化規則
1) 裁剪規則:列裁剪、分割槽裁剪、子查詢裁剪
2) 下推/合併規則:謂詞下推、函式下推、聚合下推、Limit下推
3) 去重規則:Project去重、Exchange去重、Sort去重
4) 常量摺疊/謂詞推導
- 探測優化規則
1) Joins:BroadcastHashJoin、RedistributedHashJoin、NestLoopIndexJoin
2) Aggregate:HashAggregate、SingleAggregate
3) JoinReorder
4) GroupBy下推、Exchange下推、Sort下推
- 高階優化規則
1) CTE
除了這些,我們創新性引入了兩個關鍵功能:儲存感知的優化和高效實時取樣。
5.1.1、儲存感知的優化
執行下推。執行下推是將SQL中可以依賴儲存能力的關係代數計算進行提取,將查詢計劃等價轉換為兩部分,一部分在計算層執行,一部分下推給儲存層執行。由於原有查詢計劃中並沒有明確的界限來分隔兩部分,因此需要依賴儲存層本身的計算能力,通過關係代數的等價轉換規則,將其分離。執行下推在很多分散式資料庫中都有類似的實現,但下推運算元的極致基本都是以單列條件的AND操作為主,其他運算元如函式、JOIN等都在計算層實現。這主要是由於其並未實現儲存層向上註冊計算能力的邏輯,預設認為儲存層最多隻能做單列或者組合條件的過濾。
AnalyticDB引入了一種STARs模型作為執行下推的框架,通過將異構資料來源的執行能力按照關係代數的維度進行抽象,將儲存的能力特徵化為其所能處理的關係代數的能力。在優化器完成初步的分散式執行計劃後,利用動態規劃的方式針對不同的資料來源將適合下推給儲存執行的關係代數運算元進行封裝,轉化為對應的儲存的API呼叫。
圖11 STARs模型
於此同時,STARs框架還加入了代價的計算,也就是說並非簡單的依賴儲存的能力進行執行下推,而是在對其進行關係代數能力抽象的同時,對其執行的代價進行數值化。在進行動態規劃時,將代價和執行能力同時作為參考因素,避免盲目的下推導致效能變差。
Join下推。資料重分佈是分散式資料庫執行計劃區別於傳統資料庫執行計劃的一個重要方面,主要是由於資料的物理分佈特性與關係代數的邏輯語義不匹配導致的。比如SQL:SELECT t.tid, count(*) FROM t JOIN s in t.sid = s.sid GROUP BY t.tid。其中t表按照tid進行Hash分割槽,s表按照sid進行Hash分割槽。其邏輯執行計劃如下:
基於規則的優化器。在生成Aggregation/Join的執行計劃時,會發現其下游節點並不符合當前運算元對資料物理分佈特性的要求,因此會強制增加一個數據資料重分佈的運算元來保證其執行語義的正確,資料重分佈帶來的物理開銷非常大,涉及到資料的序列化、反序列化、網路開銷等等,因此避免多次資料重分佈是對於分散式計算是一個非常重要的優化。AnalyticDB的優化器可以通過將所有可能的執行計劃進行展開,並對其進行代價計算。正是使用了這種方式,AnalyticDB實現了在不同的資料規模時,生成對應其資料特徵最優的執行計劃。
圖12 Aggregation/Join執行計劃產生
基於索引的Join和聚合 。將Join變為查詢現有索引,全索引的設計進一步消除了構建雜湊開銷。當調整Join的順序時,如果大多數Join列是分割槽列且具有索引,優化器會避免使用BushyTree,而更傾向選擇LeftDeepTree。採用LeftDeepTree,AnalyticDB能更好地利用現有索引。優化器更近一步下推了謂詞和聚合。聚合函式,比如count和查詢過濾可以直接基於索引計算。所有這些組合降低了查詢延遲,同時提高叢集利用率,從而使得AnalyticDB能輕鬆支援高併發。
圖13 基於索引的Join優化
5.1.2、高效實時取樣
統計資訊是優化器在做基於代價查詢優化所需的基本資訊,通常包括有關表、列和索引等的統計資訊。傳統資料倉庫僅收集有限的統計資訊,例如列上典型的最常值(MFV)。商業資料庫為使用者提供了收集統計資訊的工具,但這通常取決於DBA的經驗,依賴DBA來決定收集哪些統計資料,並依賴於服務或工具供應商。
上述方法收集的統計資料通常都是靜態的,它可能需要在一段時間後,或者當資料更改達到一定程度,來重新收集。但是,隨著業務應用程式變得越來越複雜和動態,預定義的統計資訊收集可能無法以更有針對性的方式幫助查詢。例如,使用者可以選擇不同的聚合列和列數,其組合可能會有很大差異。但是,在查詢生成之前很難預測這樣的組合。因此,很難在統計收集時決定正確統計方案。但是,此類統計資訊可幫助優化器做出正確決定。
我們設計了一個查詢驅動的動態統計資訊收集機制來解決此問題。守護程式動態監視傳入的查詢工作負載和特點以提取其查詢模式,並基於查詢模式,分析缺失和有益的統計資料。在此分析和預測之上,非同步統計資訊收集任務在後臺執行。這項工作旨在減少收集不必要的統計資料,同時使大多數即將到來的查詢受益。對於前面提到的聚合示例,收集多列統計資訊通常很昂貴,尤其是當用戶表有大量列的時候。根據我們的動態工作負載分析和預測,可以做到僅收集必要的多列統計資訊,同時,優化器能夠利用這些統計資料來估計聚合中不同選項的成本並做出正確的決策。
5.2、執行引擎
在優化器之下,AnalyticDB在MPP架構基礎上,採用流水線執行的DAG架構,構建了一個適用於低延遲和高吞吐量工作負載的執行器。AnalyticDB的列式執行引擎能夠充分利用底層的行列混合儲存。與行式執行引擎相比,當前的向量化執行引擎更加快取友好,能避免將不必要的資料載入到記憶體中。
圖14 流水線模式執行引擎
與許多 OLAP 系統一樣,AnalyticDB在執行時利用程式碼生成器(CodeGen) 來提高 CPU 密集型計算的效能。AnalyticDB的CodeGen基於 ANTLR ASM來動態生成表示式的程式碼樹。同時此 CodeGen 引擎還將執行時因素納入考慮,讓AnalyticDB能在Task級別利用異構新硬體的能力。例如,如果叢集中CPU支援 AVX-512指令集,我們通過生成位元組碼使用SIMD來提高效能。在此之外,通過整合內部資料表示形式,在儲存層和執行引擎之間,AnalyticDB是能夠直接對序列化二進位制資料進行操作,而不是Java 物件。這有助於消除序列化和去序列化的開銷,這在大資料量shuffle時可能會節約20%以上的時間。
6、 實驗資料展示
6.1、實驗準備
- 實驗環境。實驗執行在一個擁有八臺機器的叢集環境上,每天機器配置為Intel Xeon Platinum 8163 CPU (@2.50GHz)、300GB記憶體、3TB SSD和萬兆網絡卡。叢集上分配了一個擁有4個協調節點、4個寫節點、32個讀節點的AnalyticDB例項。
- 實驗測試集。實驗選擇了兩種測試集:一個是阿里巴巴集團內部產生的真實資料集,分別為1TB和10TB大小;一個是標準TPC-H測試集。
- 查詢語句。針對真實資料集,選擇了三種類型的查詢語句,如表1所示,它們分別為全表掃描、點查詢、多表關聯查詢。
表1 真實資料集上的三種類型查詢
6.2、實驗資料
真實資料集。圖14展示了AnalyticDB在真實資料集上執行三種查詢語句的效能。
圖15 1TB和10TB資料量的查詢延遲
如圖所示,得益於全索引設計和行列混存儲存模式,AnalyticDB均可以在秒級甚至更短的時間內完成三種類型的查詢語句。對於任意一種查詢,AnalyticDB均可以精準定位到對應的一級分割槽或二級分割槽,並進行索引篩選,從而避免無效、大量的全表資料掃描。也正是因為AnalyticDB能快速定位、掃描有效資料,1TB和10TB資料量的查詢效能差別不大,也即AnalyticDB的效能受資料表大小影響有限。
圖16 TPC-H效能
TPC-H資料集。圖15展示了AnalyticDB在1TB TPC-H資料集下的效能,同時還和PrestoDB、Spark-SQL、Greenplum進行了對比。得益於流水線處理、全列索引、行列混存、執行時索引路徑選擇、K路歸併、向量化執行引擎、CodeGen等優化機制,AnalyticDB獲得了最優的TCP-H測試執行時間,並比第二好的Greenplum快了近2倍。
原文連結
本文為雲棲社群原創內容,未經