1. 程式人生 > >萬字長文揭祕:阿里如何實現海量資料實時分析?

萬字長文揭祕:阿里如何實現海量資料實時分析?

640?wx_fmt=jpeg

阿里妹導讀:隨著資料量的快速增長,越來越多的企業迎來業務資料化時代,資料成為了最重要的生產資料和業務升級依據。本文由阿里AnalyticDB團隊出品,近萬字長文,首次深度解讀阿里在海量資料實時分析領域的多項核心技術。


數字經濟時代已經來臨,希望能和業界同行共同探索,加速行業數字化升級,服務更多中小企業和消費者。

歡迎轉發、收藏此文


挑戰


隨著資料量的快速增長,越來越多的企業迎來業務資料化時代,資料成為了最重要的生產資料和業務升級依據。伴隨著業務對海量資料實時分析的需求越來越多,資料分析技術這兩年也迎來了一些新的挑戰和變革:


  • 線上化和高可用,離線和線上的邊界越來越模糊,一切資料皆服務化、一切分析皆線上化。

  • 高併發低延時,越來越多的資料系統直接服務終端客戶,對系統的併發和處理延時提出了新的互動性挑戰。

  • 混合負載, 一套實時分析系統既要支援資料加工處理,又要支援高併發低延時的互動式查詢。

  • 融合分析, 隨著對資料新的使用方式探索,需要解決結構化與非結構化資料融合場景下的資料檢索和分析問題。


阿里巴巴最初通過單節點Oracle進行準實時分析, 後來轉到Oracle RAC,隨著業務的飛速發展, 集中式的Shared Storage架構需要快速轉向分散式,遷移到了Greenplum,但不到一年時間便遇到擴充套件性和併發的嚴重瓶頸。為了迎接更大資料集、更高併發、更高可用、更實時的資料應用發展趨勢,從2011年開始,線上分析這個技術領域,阿里實時數倉堅定的走上了自研之路。

 

640?wx_fmt=png


分析型資料庫AnalyticDB


AnalyticDB是阿里巴巴自主研發、唯一經過超大規模以及核心業務驗證的PB級實時資料倉庫。自2012年第一次在集團釋出上線以來,至今已累計迭代釋出近百個版本,支撐起集團內的電商、廣告、菜鳥、文娛、飛豬等眾多線上分析業務。


AnalyticDB於2014年在阿里雲開始正式對外輸出,支撐行業既包括傳統的大中型企業和政府機構,也包括眾多的網際網路公司,覆蓋外部十幾個行業。AnalyticDB承接著阿里巴巴廣告營銷、商家資料服務、菜鳥物流、盒馬新零售等眾多核心業務的高併發分析處理, 每年雙十一上述眾多實時分析業務高峰驅動著AnalyticDB不斷的架構演進和技術創新。


經過這2年的演進和創新,AnalyticDB已經成長為相容MySQL 5.x系列、並在此基礎上增強支援ANSI SQL:2003的OLAP標準(如window function)的通用實時數倉,躋身為實時數倉領域極具行業競爭力的產品。近期,AnalyticDB成功入選了全球權威IT諮詢機構Forrester釋出"The Forrester Wave™: CloudData Warehouse,Q4 2018"研究報告的Contenders象限,以及Gartner釋出的分析型資料管理平臺報告 (Magic Quadrant forData Management Solutions for Analytics),開始進入全球分析市場。AnalyticDB旨在幫客戶將整個資料分析和價值化從傳統的離線分析帶到下一代的線上實時分析模式。


整體架構


經過過去2年的架構演進和功能迭代,AnalyticDB當前整體架構如下圖。


AnalyticDB是一個支援多租戶的Cloud Native Realtime Data Warehouse平臺,每個租戶DB的資源隔離,每個DB都有相應獨立的模組(圖中的Front Node, Compute Node, Buffer Node),在處理實時寫入和查詢時,這些模組都是資源(CPU, Memory)使用密集型的服務,需要進行DB間隔離保證服務質量。同時從功能完整性和成本優化層面考慮,又有一系列叢集級別服務(圖中綠色部分模組)。


640?wx_fmt=png


下面是對每個模組的具體描述:


DB級別服務元件:


  • Front Node:負責JDBC, ODBC協議層接入,認證和鑑權,SQL解析、重寫;分割槽地址路由和版本管理;同時優化器,執行計劃和MPP計算的排程模組也在Front Node。

  • Compute Node: 包含MPP計算Worker模組,和儲存模組(行列混存,元資料,索引)。

  • Buffer Node: 負責實時寫入,並根據實時資料大小觸發索引構建和合並。


叢集級別服務元件:


  • Management Console: 管理控制檯。

  • Admin Service:叢集管控服務,負責計量計費,例項生命週期管理等商業化功能,同時提供OpenAPI和InnerAPI給Management Console和第三方呼叫。

  • Global Meta Service:全域性元資料管理,提供每個DB的元資料管理服務,同時提供分割槽分配,副本管理,版本管理,分散式DDL等能力。

  • Job Service:作業服務,提供非同步作業排程能力。非同步作業包括索引構建、擴容、無縫升級、刪庫刪表的後臺非同步資料清理等。

  • Connector Service:資料來源連線服務,負責外部各資料來源(圖中右側部分)接入到AnalyticDB。目前該服務開發基本完成,即將上線提供雲服務。

  • Monitoring & Alerting Service:監控告警診斷服務,既提供面向內部人員的運維監控告警診斷平臺,又作為資料來源通過Management Console面向使用者側提供資料庫監控服務。

  • Resource Management Service:資源管理服務,負責叢集級別和DB級別服務的建立、刪除、DNS/SLB掛載/解除安裝、擴縮容、升降配,無縫升級、服務發現、服務健康檢查與恢復。


資料模型


AnalyticDB中表組(Table Group)分為兩類:事實表組和維度表組。


  • 事實表組(Fact Table Group),表組在AnalyticDB裡是一個邏輯概念,使用者可以將業務上關聯性比較多的事實表放在同一個事實表組下,主要是為了方便客戶做眾多資料業務表的管理,同時還可以加速Co-location Join計算。

  • 維度表組(Dimension Table Group),用於存放維度表,目前有且僅有一個,在資料庫建立時會自動建立,維度表特徵上是一種資料量較小但是需要和事實表進行潛在關聯的表。


AnalyticDB中表分為事實表(Fact Table)和維度表(Dimension Table)。


事實表建立時至少要指定Hash分割槽列和相關分割槽資訊,並且指定存放在一個表組中,同時支援List二級分割槽。


  • Hash Partition將資料按照分割槽列進行hash分割槽,hash分割槽被分佈到多個Compute Node中。

  • List Partition(如果指定List分割槽列的話)對一個hash分割槽進行再分割槽,一般按照時間(如每天一個list分割槽)。

  • 一個Hash Partition的所有List Partition預設存放於同一個Compute Node中。每個Hash Partition配有多個副本(通常為雙副本),分佈在不同的Compute      Node中,做到高可用和高併發。


維度表可以和任意表組的任意表進行關聯,並且建立時不需要配置分割槽資訊,但是對單表資料量大小有所限制,並且需要消耗更多的儲存資源,會被儲存在每個屬於該DB的Compute Node中。


下圖描述了從Database到List分割槽到資料模型:


640?wx_fmt=png


對於Compute Node 來說,事實表的每個List分割槽是一個物理儲存單元(如果沒有指定List分割槽列,可認為該Hash分割槽只有一個List分割槽)。一個分割槽物理儲存單元採用行列混存模式,配合元資料和索引,提供高效查詢。


海量資料


基於上述資料模型,AnalyticDB提供了單庫PB級資料實時分析能力。以下是生產環境的真實資料:


  • 阿里巴巴集團某營銷應用單DB表數超過20000張

  • 雲上某企業客戶單DB資料量近3PB,單日分析查詢次數超過1億

  • 阿里巴巴集團內某單個AnalyticDB叢集超過2000臺節點規模

  • 雲上某業務實時寫入壓力高達1000w TPS

  • 菜鳥網路某資料業務極度複雜分析場景,查詢QPS 100+


匯入匯出


靈活的資料匯入匯出能力對一個實時數倉來說至關重要,AnalyticDB當前既支援通過阿里雲資料傳輸服務DTS、DataWorks資料整合從各種外部資料來源匯入入庫,同時也在不斷完善自身的資料匯入能力。整體匯入匯出能力如下圖(其中匯入部分資料來源當前已支援,部分在開發中,即將釋出)。

 

640?wx_fmt=png


★ 資料匯入


首先,由於AnalyticDB相容MySQL5.x系列,支援通過MySQL JDBC方式把資料insert入庫。為了獲得最佳寫入效能,AnalyticDB提供了Client SDK,實現分割槽聚合寫的優化,相比通過JDBC單條insert,寫入效能有10倍以上提升。對於應用端業務邏輯需要直接寫入AnalyticDB的場景,推薦使用AnalyticDB Client SDK。


同時,對於快速上傳本地結構化的文字檔案,可以使用基於AnalyticDB Client SDK開發的Uploader工具。對於特別大的檔案,可以拆分後使用uploader工具進行並行匯入。


另外,對於OSS,MaxCompute這樣的外部資料來源,AnalyticDB通過分散式的Connector Service資料匯入服務併發讀取並寫入到相應DB中。Connector Service還將支援訂閱模式,從Kafka,MQ,RDS等動態資料來源把資料匯入到相應DB中。AnalyticDB對大資料生態的Logstash,Fluentd,Flume等日誌收集端、ETL工具等通過相應外掛支援,能夠快速把資料寫入相應DB。


今天在阿里巴巴集團內,每天有數萬張表從MaxCompute匯入到AnalyticDB中進行線上分析,其中大量匯入任務單表資料大小在TB級、資料量近千億。


★ 資料匯出


AnalyticDB目前支援資料匯出到OSS和MaxCompute,業務場景主要是把相應查詢結果在外部儲存進行儲存歸檔,實現原理類似insert from select操作。insert from select是把查詢結果寫入到內部表,而匯出操作則是寫入外部儲存, 通過改進實現機制,可以方便地支援更多的匯出資料來源。


核心技術


高效能SQL Parser


AnalyticDB經過數年的發展,語法解析器也經歷了多次更新迭代。曾經使用過業界主流的 Antlr(http://www.antlr.org),JavaCC(https://javacc.org)等Parser生成器作為SQL 語法解析器,但是兩者在長期、大規模、複雜查詢場景下,Parser的效能、語法相容、API設計等方面不滿足要求,於是我們引入了自研的SQL Parser元件FastSQL。


★ 領先業界的Parser效能


AnalyticDB主打的場景是高併發、低延時的線上化分析,對SQL Parser效能要求很高,批量實時寫入等場景要求更加苛刻。FastSQL通過多種技術優化提升Parser效能,例如:


  • 快速對比:使用64位hash演算法加速關鍵字匹配,使用fnv_1a_64 hash演算法,在讀取identifier的同時計算好hash值,並利用hash64低碰撞概率的特點,使用64位hash code直接比較,比常規Lexer先讀取identifier,在查詢SymbolTable速度更快。

  • 高效能的數值Parser:Java自帶的Integer.parseInt()/Float.parseFloat()需要構造字串再做parse,FastSQL改進後可以直接在原文字上邊讀取邊計算數值。

  • 分支預測:在insert values中,出現常量字面值的概率比出現其他的token要高得多,通過分支預測可以減少判斷提升效能。


以TPC-DS99個Query對比來看,FastSQL比Antlr Parser(使用Antlr生成)平均快20倍,比JSQLParser(使用JavaCC生成)平均快30倍,在批量Insert場景、多列查詢場景下,使用FastSQL後速度提升30~50倍。


640?wx_fmt=png


★ 無縫結合優化器


在結合AnalyticDB的優化器的SQL優化實踐中,FastSQL不斷將SQL Rewrite的優化能力前置化到SQL Parser中實現,通過與優化器的SQL優化能力協商,將盡可能多的表示式級別優化前置化到SQL Parser中,使得優化器能更加專注於基於代價和成本的優化(CBO,Cost-Based Optimization)上,讓優化器能更多的集中在理解計算執行計劃優化上。FastSQL在AST Tree上實現了許多SQL Rewrite的能力,例如:


  • 常量摺疊



  
SELECT * FROM t1 t
WHERE comm_week 
  BETWEEN CAST(date_format(date_add('day',-day_of_week('20180605'),
                             date('20180605')),'%Y%m%d') AS bigint)
        AND CAST(date_format(date_add('day',-day_of_week('20180605')
                            ,date('20180605')),'%Y%m%d') AS bigint)
------>
SELECT * FROM t1 t
WHERE comm_week BETWEEN20180602AND20180602


  • 函式變換:



  
SELECT * FROM t1 t
WHERE DATE_FORMAT(t."pay_time",'%Y%m%d')>='20180529'
    AND DATE_FORMAT(t."pay_time",'%Y%m%d')<='20180529'
------>
SELECT * FROM t1 t
WHERE t."pay_time">= TIMESTAMP'2018-05-29 00:00:00'
AND t."pay_time"< TIMESTAMP'2018-05-30 00:00:00'


  • 表示式轉換:



  
SELECT a, b FROM t1
WHERE b +1=10;
------>
SELECT a, b FROM t1
WHERE b =9;


  • 函式型別推斷:



  
-- f3型別是TIMESTAMP型別
SELECT concat(f3,1)
FROM nation;
------>
SELECT concat(CAST(f3 AS CHAR),'1')
FROM nation;


  • 常量推斷:


  

SELECT
* FROM t
WHERE a < b AND b = c AND a =5
------>
SELECT * FROM t
WHERE b >5AND a =5AND b = c


  • 語義去重:



  
SELECT * FROM t1
WHERE max_adate >'2017-05-01'
    AND max_adate !='2017-04-01'
------>
SELECT * FROM t1
WHERE max_adate > DATE '2017-05-01'


玄武儲存引擎


為保證大吞吐寫入,以及高併發低時延響應,AnalyticDB自研儲存引擎玄武,採用多項創新的技術架構。玄武儲存引擎採用讀/寫例項分離架構,讀節點和寫節點可分別獨立擴充套件,提供寫入吞吐或者查詢計算能力。在此架構下大吞吐資料寫入不影響查詢分析效能。同時玄武儲存引擎構築了智慧全索引體系,保證絕大部分計算基於索引完成,保證任意組合條件查詢的毫秒級響應。


 讀寫分離架構支援大吞吐寫入


傳統資料倉庫並沒有將讀和寫分開處理,即這些資料庫程序/執行緒處理請求的時候,不管讀寫都會在同一個例項的處理鏈路上進行。因此所有的請求都共享同一份資源(記憶體資源、鎖資源、IO資源),並相互影響。在查詢請求和寫入吞吐都很高的時候,會存在嚴重的資源競爭,導致查詢效能和寫入吞吐都下降。


為了解決這個問題,玄武儲存引擎設計了讀寫分離的架構。如下圖所示,玄武儲存引擎有兩類關鍵的節點:Buffer Node和Compute Node。Buffer Node專門負責處理寫請求,Compute Node專門負責查詢請求,Buffer Node和Compute Node完全獨立並互相不影響,因此,讀寫請求會在兩個完全不相同的鏈路中處理。上層的Front Node會把讀寫請求分別路由給Buffer Node和Compute Node。


640?wx_fmt=png


實時寫入鏈路:


  • 業務實時資料通過JDBC/ODBC協議寫入到Front Node。

  • Front Node根據實時資料的hash分割槽列值,路由到相應Buffer Node。

  • Buffer Node將該實時資料的內容(類似於WAL)提交到盤古分散式檔案系統,同時更新實時資料版本,並返回Front  Node,Front Node返回寫入成功響應到客戶端。

  • Buffer Node同時會非同步地把實時資料內容推送到Compute Node,Compute Node消費該實時資料並構建實時資料輕量級索引。

  • 當實時資料積攢到一定量時,Buffer Node觸發後臺Merge Baseline作業,對實時資料構建完全索引並與基線資料合併。


實時查詢鏈路:


  • 業務實時查詢請求通過JDBC/ODBC協議傳送到Front Node。

  • Front Node首先從Buffer Node拿到當前最新的實時資料版本,並把該版本隨執行計劃一起下發到Compute Node。

  • Compute Node檢查本地實時資料版本是否滿足實時查詢要求,若滿足,則直接執行並返回資料。若不滿足,需先到Buffer Node把指定版本的實時資料拖到本地,再執行查詢,以保證查詢的實時性(強一致)。


AnalyticDB提供強實時和弱實時兩種模式,強實時模式執行邏輯描述如上。弱實時模式下,Front Node查詢請求則不帶版本下發,返回結果的實時取決於Compute Node對實時資料的處理速度,一般有秒極延遲。所以強實時在保證資料一致性的前提下,當實時資料寫入量比較大時對查詢效能會有一定的影響。


高可靠性


玄武儲存引擎為Buffer Node和Compute Node提供了高可靠機制。使用者可以定義Buffer Node和Compute Node的副本數目(預設為2),玄武保證同一個資料分割槽的不同副本一定是存放在不同的物理機器上。Compute Node的組成採用了對等的熱副本服務機制,所有Compute Node節點都可以參與計算。另外,Computed Node的正常執行並不會受到Buffer Node節點異常的影響。如果Buffer Node節點異常導致Compute Node無法正常拉取最新版本的資料,Compute Node會直接從盤古上獲取資料(即便這樣需要忍受更高的延遲)來保證查詢的正常執行。資料在Compute Node上也是備份儲存。如下圖所示,資料是通過分割槽存放在不同的ComputeNode上,具有相同hash值的分割槽會儲存在同一個Compute Node上。資料分割槽的副本會儲存在其他不同的Compute Node上,以提供高可靠性。


640?wx_fmt=png

 

高擴充套件性


玄武的兩個重要特性設計保證了其高可擴充套件性:1)Compute Node和Buffer Node都是無狀態的,他們可以根據業務負載需求進行任意的增減;2)玄武並不實際儲存資料,而是將資料存到底層的盤古系統中,這樣,當Compute Node和Buffer Node的數量進行改變時,並不需要進行實際的資料遷移工作。


 為計算而生的儲存


資料儲存格式


傳統關係型資料庫一般採用行儲存(Row-oriented Storage)加B-tree索引,優勢在於其讀取多列或所有列(SELECT *)場景下的效能,典型的例子如MySQL的InnoDB引擎。但是在讀取單列、少數列並且行數很多的場景下,行儲存會存在嚴重的讀放大問題。

資料倉庫系統一般採用列儲存(Column-oriented Storage),優勢在於其單列或少數列查詢場景下的效能、更高的壓縮率(很多時候一個列的資料具有相似性,並且根據不同列的值型別可以採用不同的壓縮演算法)、列聚合計算(SUM, AVG, MAX, etc.)場景下的效能。但是如果使用者想要讀取整行的資料,列儲存會帶來大量的隨機IO,影響系統性能。

為了發揮行儲存和列儲存各自的優勢,同時避免兩者的缺點,AnalyticDB設計並實現了全新的行列混存模式。如下圖所示:


640?wx_fmt=png


  • 對於一張表,每k行資料組成一個Row Group。在每個Row Group中,每列資料連續的存放在單獨的block中,每Row Group在磁碟上連續存放。

  • Row Group內列block的資料可按指定列(聚集列)排序存放,好處是在按該列查詢時顯著減少磁碟隨機IO次數。

  • 每個列block可開啟壓縮。


行列混存儲存相應的元資料包括:分割槽元資料,列元資料,列block元資料。其中分割槽元資料包含該分割槽總行數,單個block中的列行數等資訊;列元資料包括該列值型別、整列的MAX/MIN值、NULL值數目、直方圖資訊等,用於加速查詢;列block元資料包含該列在單個Row Group中對應的MAX/MIN/SUM、總條目數(COUNT)等資訊,同樣用於加速查詢。


全索引計算


使用者的複雜查詢可能會涉及到各種不同的列,為了保證使用者的複雜查詢能夠得到秒級響應,玄武儲存引擎在行列混合儲存的基礎上,為基線資料(即歷史資料)所有列都構建了索引。玄武會根據列的資料特徵和空間消耗情況自動選擇構建倒排索引、點陣圖索引或區間樹索引等,而用的最多的是倒排索引。


640?wx_fmt=png


如上圖所示,在倒排索引中,每列的數值對應索引的key,該數值對應的行號對應索引的value,同時所有索引的key都會進行排序。依靠全列索引,交集、並集、差集等資料庫基礎操作可以高效能地完成。如下圖所示,使用者的一個複雜查詢包含著對任意列的條件篩選。玄武會根據每個列的條件,去索引中篩選滿足條件的行號,然後再將每列篩選出的行號,進行交、並、差操作,篩選出最終滿足所有條件的行號。玄武會依據這些行號去訪問實際的資料,並返回給使用者。通常經過篩選後,滿足條件的行數可能只佔總行數的萬分之一到十萬分之一。因此,全列索引幫助玄武在執行查詢請求的時候,大大減小需要實際遍歷的行數,進而大幅提升查詢效能,滿足任意複雜查詢秒級響應的需求。


640?wx_fmt=png


使用全列索引給設計帶來了一個很大挑戰:需要對大量資料構建索引,這會是一個非常耗時的過程。如果像傳統資料庫那樣在資料寫入的路徑上進行索引構建,那麼這會嚴重影響寫入的吞吐,而且會嚴重拖慢查詢的效能,影響使用者體驗。為了解決這個挑戰,玄武採用了非同步構建索引的方式。當寫入請求到達後,玄武把寫SQL持久化到盤古,然後直接返回,並不進行索引的構建。


當這些未構建索引的資料(稱為實時資料)積累到一定數量時,玄武會開啟多個MapReduce任務,來對這些實時資料進行索引的構建,並將實時資料及其索引,同當前版本的基線資料(歷史資料)及其索引進行多版本歸併,形成新版本的基線資料和索引。這些MapReduce任務通過伏羲進行分散式排程和執行,非同步地完成索引的構建。這種非同步構建索引的方式,既不影響AnalyticDB的高吞吐寫入,也不影響AnalyticDB的高效能查詢。


非同步構建索引的機制還會引入一個新問題:在進行MapReduce構建索引的任務之前,新寫入的實時資料是沒有索引的,如果使用者的查詢會涉及到實時資料,查詢效能有可能會受到影響。玄武採用為實時資料構建排序索引(Sorted Index)的機制來解決這個問題。


如下圖所示,玄武在將實時資料以block形式刷到磁碟之前,會根據每一列的實時資料生成對應的排序索引。排序索引實際是一個行號陣列,對於升序排序索引來說,行號陣列的第一個數值是實時資料最小值對應的行號,第二個數值是實時資料第二小值對應的行號,以此類推。這種情況下,對實時資料的搜尋複雜度會從O(N)降低為O(lgN)。排序索引大小通常很小(60KB左右),因此,排序索引可以快取在記憶體中,以加速查詢。


640?wx_fmt=png

羲和計算引擎


針對低延遲高併發的線上分析場景需求,AnalyticDB自研了羲和大規模分析引擎,其中包括了基於流水線模型的分散式平行計算引擎,以及基於規則 (Rule-Based Optimizer,RBO) 和代價(Cost-Based Optimizer,CBO)的智慧查詢優化器。

 

★   優化器


優化規則的豐富程度是能否產生最優計劃的一個重要指標。因為只有可選方案足夠多時,才有可能選到最優的執行計劃。AnalyticDB提供了豐富的關係代數轉換規則,用來確保不會遺漏最優計劃。


基礎優化規則:


  • 裁剪規則:列裁剪、分割槽裁剪、子查詢裁剪

  • 下推/合併規則:謂詞下推、函式下推、聚合下推、Limit下推

  • 去重規則:Project去重、Exchange去重、Sort去重

  • 常量摺疊/謂詞推導


探測優化規則:


  • Joins:BroadcastHashJoin、RedistributedHashJoin、NestLoopIndexJoin

  • Aggregate:HashAggregate、SingleAggregate

  • JoinReordering

  • GroupBy下推、Exchange下推、Sort下推


高階優化規則:CTE

 

例如下圖中,CTE的優化規則的實現將兩部分相同的執行邏輯合為一個。通過類似於最長公共子序列的演算法,對整個執行計劃進行遍歷,並對一些可以忽略的運算元進行特殊處理,如Projection,最終達到減少計算的目的。


640?wx_fmt=png


單純基於規則的優化器往往過於依賴規則的順序,同樣的規則不同的順序會導致生成的計劃完全不同,結合基於代價的優化器則可以通過嘗試各種可能的執行計劃,達到全域性最優。

 

AnalyticDB的代價優化器基於Cascade模型,執行計劃經過Transform模組進行了等價關係代數變換,對可能的等價執行計劃,估算出按Cost Model量化的計劃代價,並從中最終選擇出代價最小的執行計劃通過Plan Generation模組輸出,存入Plan Cache(計劃快取),以降低下一次相同查詢的優化時間。

 

640?wx_fmt=png

 

線上分析的場景對優化器有很高的要求,AnalyticDB為此開發了三個關鍵特性:儲存感知優化、動態統計資訊收集和計劃快取。


儲存層感知優化


生成分散式執行計劃時,AnalyticDB優化器可以充分利用底層儲存的特性,特別是在Join策略選擇,Join Reorder和謂詞下推方面。


  • 底層資料的雜湊分佈策略將會影響Join策略的選擇。基於規則的優化器,在生成Join的執行計劃時,如果對資料物理分佈特性的不感知,會強制增加一個數據重分佈的運算元來保證其執行語義的正確。 資料重分佈帶來的物理開銷非常大,涉及到資料的序列化、反序列化、網路開銷等等,因此避免多次資料重分佈對於分散式計算是非常重要的。除此之外,優化器也會考慮對資料庫索引的使用,進一步減少Join過程中構建雜湊的開銷。

  • 調整Join順序時,如果大多數Join是在分割槽列,優化器將避免生成Bushy Tree,而更偏向使用Left Deep Tree,並儘量使用現有索引進行查詢。

640?wx_fmt=png

  • 優化器更近一步下推了謂詞和聚合。聚合函式,比如count(),和查詢過濾可以直接基於索引計算。

 

所有這些組合降低了查詢延遲,同時提高叢集利用率,從而使得AnalyticDB能輕鬆支援高併發。


動態統計資訊收集


統計資訊是優化器在做基於代價查詢優化所需的基本資訊,通常包括有關表、列和索引等的統計資訊。傳統資料倉庫僅收集有限的統計資訊,例如列上典型的最常值(MFV)。商業資料庫為使用者提供了收集統計資訊的工具,但這通常取決於DBA的經驗,依賴DBA來決定收集哪些統計資料,並依賴於服務或工具供應商。


上述方法收集的統計資料通常都是靜態的,它可能需要在一段時間後,或者當資料更改達到一定程度,來重新收集。但是,隨著業務應用程式變得越來越複雜和動態,預定義的統計資訊收集可能無法以更有針對性的方式幫助查詢。例如,使用者可以選擇不同的聚合列和列數,其組合可能會有很大差異。但是,在查詢生成之前很難預測這樣的組合。因此,很難在統計收集時決定正確統計方案。但是,此類統計資訊可幫助優化器做出正確決定。


我們設計了一個查詢驅動的動態統計資訊收集機制來解決此問題。守護程式動態監視傳入的查詢工作負載和特點以提取其查詢模式,並基於查詢模式,分析缺失和有益的統計資料。在此分析和預測之上,非同步統計資訊收集任務在後臺執行。這項工作旨在減少收集不必要的統計資料,同時使大多數即將到來的查詢受益。對於前面提到的聚合示例,收集多列統計資訊通常很昂貴,尤其是當用戶表有大量列的時候。根據我們的動態工作負載分析和預測,可以做到僅收集必要的多列統計資訊,同時,優化器能夠利用這些統計資料來估計聚合中不同選項的成本並做出正確的決策。


計劃快取


從線上應用案件看,大多數客戶都有一個共同的特點,他們經常反覆提交類似的查詢。在這種情況下,計劃快取變得至關重要。為了提高快取命中率,AnalyticDB不使用原始SQL文字作為搜尋鍵來快取。相反,SQL語句首先通過重寫並引數化來提取模式。例如,查詢 “SELECT * FROM t1 WHERE a = 5 + 5”將轉化為“SELECT * FROM t1 WHERE a =?”。引數化的SQL模版將被作為計劃快取的關鍵字,如果快取命中,AnalyticDB將根據新查詢進行引數繫結。由於這個改動,即使使用有限的快取大小,優化器在生產環境也可以保持高達90%以上的命中率,而之前只能達到40%的命中率。


這種方法仍然有一個問題。假設我們在列a上有索引,“SELECT * FROM t1 WHERE a = 5”的優化計劃可以將索引掃描作為其最佳訪問路徑。但是,如果新查詢是“SELECT * FROM t1 WHERE a = 0”並且直方圖告訴我們數值0在表t1佔大多數,那麼索引掃描可能不如全表掃描有效。在這種情況下,使用快取中的計劃並不是一個好的決定。為了避免這類問題,AnalyticDB提供了一個功能Literal Classification,使用列的直方圖對該列的值進行分類,僅當與模式相關聯的常量“5”的資料分佈與新查詢中常量“0”的資料分佈類似時,才實際使用快取記憶體的計劃。否則,仍會對新查詢執行常規優化。

 

★ 執行引擎


在優化器之下,AnalyticDB在MPP架構基礎上,採用流水線執行的DAG架構,構建了一個適用於低延遲和高吞吐量工作負載的執行器。如下圖所示,當涉及到多個表之間非分割槽列JOIN時,CN(MPP Worker)會先進行data exchange (shuffling)然後再本地JOIN (SourceTask),aggregate後傳送到上一個stage(MiddleTask),最後彙總到Output Task。由於絕大多情況都是in-memory計算(除複雜ETL類查詢,儘量無中間Stage 落盤)且各個stage之間都是pipeline方式協作,效能上要比MapReduce方式快一個數量級。

640?wx_fmt=png


在接下來的幾節中,將介紹其中三種特性,包括混合工作負載管理,CodeGen和向量化執行。


混合工作負載管理


作為一套完備的實時數倉解決方案,AnalyticDB中既有需要較低響應時間的高併發查詢,也有類似ETL的批處理,兩者爭用相同資源。傳統數倉體系往往在這兩個方面的兼顧性上做的不夠好。

 

AnalyticDB worker接收coordinator下發的任務, 負責該任務的物理執行計劃的實際執行。這項任務可以來自不同的查詢, worker會將任務中的物理執行計劃按照既定的轉換規則轉換成對應的operator,物理執行計劃中的每一個Stage會被轉換成一個或多個operator。

640?wx_fmt=png


執行引擎已經可以做到stage/operator級別中斷和Page級別換入換出,同時執行緒池在所有同時執行的查詢間共享。但是,這之上仍然需要確保高優先順序查詢可以獲得更多計算資源。


640?wx_fmt=png


根據經驗,客戶總是期望他們的短查詢即使當系統負載很重的時候也能快速完成。為了滿足這些要求,基於以上場景,通過時間片的分配比例來體現不同查詢的優先順序,AnalyticDB實現了一個簡單版本的類Linux kernel 的排程演算法。系統記錄了每一個查詢的總執行耗時,查詢總耗時又是通過每一個Task耗時來進行加權統計的,最終在查詢層面形成了一顆紅黑樹,每次總是挑選最左側節點進行排程,每次取出或者加入(被喚醒以及重新入隊)都會重新更新這棵樹,同樣的,在Task被喚醒加入這顆樹的時候,執行引擎考慮了補償機制,即時間片耗時如果遠遠低於其他Task的耗時,確保其在整個樹裡面的位置,同時也避免了因為長時間的阻塞造成的飢餓,類似於CFS 排程演算法中的vruntime補償機制。

640?wx_fmt=png


這個設計雖然有效解決了慢查詢佔滿資源,導致其他查詢得不到執行的問題,卻無法保障快查詢的請求延遲。這是由於軟體層面的多執行緒執行機制,執行緒個數大於了實際的CPU個數。在實際的應用中,計算執行緒的個數往往是可用Core的2倍。這也就是說,即使快查詢的運算元得到了計算執行緒資源進行計算,也會在CPU層面與慢查詢的運算元形成競爭。所下圖所示,快查詢的運算元計算執行緒被排程到VCore1上,該運算元在VCore1上會與慢查詢的計算執行緒形成競爭。另外在物理Core0上,也會與VCore0上的慢查詢的計算執行緒形成競爭。


640?wx_fmt=png


在Kernel sched模組中,對於不同優先順序的執行緒之間的搶佔機制,已經比較完善,且時效性比較高。因而,通過引入kernel層面的控制可以有效解決快查詢低延遲的問題,且無需對運算元的實現進行任何的改造。執行引擎讓高優先順序的執行緒來執行快查詢的運算元,低優先順序的執行緒來執行慢查詢的運算元。由於高優先順序執行緒搶佔低優先順序執行緒的機制,快查詢運算元自然會搶佔慢查詢的運算元。此外,由於高優先順序執行緒在Kernel sched模組排程中,具有較高的優先順序,也避免了快慢查詢運算元在vcore層面的CPU競爭。

 

640?wx_fmt=png


同樣的在實際應用中是很難要求使用者來辨別快慢查詢,因為使用者的業務本身可能就沒有快慢業務之分。另外對於線上查詢,查詢的計算量也是不可預知的。為此,計算引擎在Runtime層面引入了快慢查詢的識別機制,參考Linux kernel中vruntime的方式,對運算元的執行時間、排程次數等資訊進行統計,當運算元的計算量達到給定的慢查詢的閾值後,會把運算元從高優先順序的執行緒轉移到低優先順序的執行緒中。這有效提高了在壓力測試下快查詢的響應時間。

 

相關推薦

長文揭祕阿里如何實現海量資料實時分析

阿里妹導讀:隨著資料量的快速增長,越來越多的企業迎來業務資料化時代,資料成為了最重要的生產資料和業務升級依據。本文由阿里AnalyticDB團隊出品,近萬字長文,首次深度解讀阿里在海量資料實時分析領域的多項核心技術。 數字經濟時代已經來臨,希望能和業界同行共同探索,加速行

阿里如何實現海量資料實時分析

阿里妹導讀:隨著資料量的快速增長,越來越多的企業迎來業務資料化時代,資料成為了最重要的生產資料和業務升級依據。本文由阿里AnalyticDB團隊出品,近萬字長文,首次深度解讀阿里在海量資料實時分析領域的多項核心技術。   數字經濟時代已經來臨,希望能和業界同行共同探索,加速行

效能追擊長文30+圖揭祕8大主流伺服器程式執行緒模型 | Node.js,Apache,Nginx,Netty,Redis,Tomcat,MySQL,Zuul

> 本文為《[高效能網路程式設計遊記](https://www.itzhai.com/articles/decrypt-the-threading-model-of-common-server-programs.html)》的第六篇“效能追擊:萬字長文30+圖揭祕8大主流伺服器程式執行緒模型”。 ![ima

長文全解讀 | 淺析銀行數字化轉型之二打造金融敏捷中心

本文作者: 劉偉光,螞蟻金服副總裁,目前致力於螞蟻金服技術的商業推廣和生態建設。在加入螞蟻金服前,他在企業軟體市場深耕多年,建立Pivotal軟體大中華區分公司,開創了企業級大資料以及企業級雲端計算PaaS平臺的市場先河。在建立Pivotal中國軟體公司之前,劉偉光曾經擔任EM

習近平實施國家大資料戰略,加快建設數字中國(長文解讀)

  中共中央政治局12月8日下午就實施國家大資料戰略進行第二次集體學習。習總書記強調推動實施國家大資料戰略,加快完善數字基礎設施,推進資料資源整合和開放共享,保障資料安全,加快建設數字中國,更好服務我國經濟社會發展和人民生活改善。   中關村大資料產業聯盟 趙國棟 從數字安全、數字治理、數字經濟三大要素內涵

長文ELK(V7)部署與架構分析

ELK(7版本)部署與架構分析 1、ELK的背景介紹與應用場景   在專案應用執行的過程中,往往會產生大量的日誌,我們往往需要根據日誌來定位分析我們的伺服器專案執行情況與BUG產生位置。一般情況下直接在日誌檔案中tailf、 grep、awk 就可以獲得自己想要的資訊。但在規模較大的場

長文!不為人所知的分散式鎖實現全都在這裡了

1、引入業務場景 2、分散式鎖家族成員介紹 3、分散式鎖成員實現原理剖析 4、最後的總結 2019 已經過去! 2020 已經到站! 1、引入業務場景 首先來由一個場景引入: 最近老闆接了一個大單子,允許在某終端裝置安裝我們的APP,終端裝置廠商日活起碼得幾十萬到百萬級別,這個APP也是近期產品根據

吐血輸出2長文帶你細細盤點五種負載均衡策略。

2020 年 5 月 15 日,Dubbo 釋出 2.7.7 release 版本。其中有這麼一個 Features 新增一個負載均衡策略。 熟悉我的老讀者肯定是知道的,Dubbo 的負載均衡我都寫過專門的文章,對每個負載均衡演算法進行了原始碼的解讀,還分享了自己除錯過程中的一些騷操作。 新的負載均衡出來

why哥被阿里一道基礎面試題給幹懵了,一氣之下寫出長文

這是why的第 65 篇原創文章 荒腔走板 大家好,我是 why,歡迎來到我連續周更優質原創文章的第 65 篇。老規矩,先荒腔走板聊聊技術之外的東西。 上面這圖是去年的成都馬拉松賽道上,攝影師抓拍的我。哎,真是陽光向上的 95 後帥小夥啊。 今年由於疫情原因,上半年的馬拉松比賽全部停擺了。今年可能也沒有機

白日夢的ES筆記三長文 Elasticsearch基礎概念統一掃盲

[TOC] ### 一、導讀 本篇是白日夢的第三篇ES筆記,前面已經跟大家分享過兩篇ES筆記了,分別是: [ES基礎篇--快速上手ES](https://mp.weixin.qq.com/s/vpx-YztORgqROzPIL3_yig) [ES進階篇--50個檢索、聚合案例](https://mp

長文解讀區塊鏈7類共識演算法

摘要:本文將對區塊鏈中常見的七類共識演算法進行介紹,希望對讀者探索區塊鏈有所幫助。 區塊鏈技術起源於比特幣,最初是比特幣等數字貨幣的一種底層技術,區塊鏈融合了密碼學、組網技術、共識演算法、智慧合約等多種技術。隨著區塊鏈技術的逐漸成熟,其逐漸得到科研機構、政府、金融機構和科技企業的關注。區塊鏈具有匿名、防篡改、

幹貨手把手教你做需求管理

體驗 正常的 知識共享 ktv 實的 但是 列表 等於 啟示 通過這篇文章,總結自己在工作實踐中需求管理的方法論——普拉姆方法。總結這個方法論的特點是,用最輕量化的投入,與他人協作,並管理需求,推動需求上線。這套方法論組合了項目管理、敏捷開發的知識,希望能對大家有所幫助。

長文 | 有關大資料理解一篇文章足矣!

導讀: 科技的進步在很多時候總會超出我們的想象,試想如果未來我們一個人擁有的電腦裝置超過現在全球在計算能力的總和,一個人產生的資料量超過現在全球資料量的總和,甚至你的寵物小狗產生的資訊量都超過現在全球資料量的總和,世界會發生什麼呢?那就取決於你的想象力了。 很多初學者,對大資料的概念都是模糊

《深入理解 Java 記憶體模型》讀書筆記(下)(乾貨,長文

0. 前提 1. 基礎 2. 重排序 3. 順序一致性 4. Volatile 5. 鎖 6. final 7. 總結 4. Volatile 4.1 VOLATILE 特性 舉個例子: publ

《深入理解 Java 記憶體模型》讀書筆記(上)(乾貨,長文

0. 前提 1. 基礎 2. 重排序 3. 順序一致性 4. Volatile 5. 鎖 6. final 7. 總結 0. 前提 《深入理解 Java 記憶體模型》 程曉明著,該書在以前看過一

資料治理怎麼做?這篇長文終於講清楚了!

引言: 股份制改革對我國銀行業來說只是一個開始,企業在風險管理、創造價值等方面還有很長的路要走。風險管理要求提供精準的資料模型、創造價值要求充分銀行資料資產,這是資料治理的外部推動因素。此外,隨著第三次工業革命的到來,銀行業也需要進入定製化時代,以更低的成本,生產多樣化的金融產品,從而滿足不同顧

長文 | 微軟的軟體工程數字化轉型

  使用現代工程實踐,微軟核心服務開發與工程(CSE,前身為Microsoft IT)團隊可以快速有效地響應,以滿足內部客戶和合作夥伴的業務需求。微軟的開發平臺Visual Studio Team Services(Visual Studio 團隊服務,VSTS)提供並內建了

Python分散式爬蟲!你以為你會了嗎?你看看這篇教程!長文

背景一、前沿1.1 爬蟲是什麼?網路爬蟲(又被稱為網頁蜘蛛,網路機器人,在FOAF社群中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動的抓取全球資訊網資訊的程式或者指令碼。1.2 為什麼是Python?簡單易學:簡單到沒有學習過任何程式語言的人稍微看下資料就能編寫出

長文深度解析Python裝飾器

Python 中的裝飾器是你進入 Python 大門的一道坎,不管你跨不跨過去它都在那裡。 為什麼需要裝飾器 我們假設你的程式實現了 say_hello () 和 say_goodbye () 兩個函式。       def say_

長文|如何直觀解釋卷積神經網路的工作原理?

作者:YJango 日本會津大學|人機互動實驗室博士生 量子位 已獲授權編輯釋出 該文是對卷積神經網路的介紹,並假設你理解前饋神經網路。 如果不是,強烈建議讀完《如何簡單形象又有趣地講解神經網路是什麼?》這篇文章後後再來讀該篇。 推薦文章連結: https://www.zhihu.com/ques