SQL On Hadoop 設計的一個基本原則是:將計算任務移動到資料所在的節點而不是反過來

來源:互聯網
上載者:User

標籤:query   zip   利用   tor   命中率   產生   shuff   style   讀取資料   

3.1 資料本地化

SQL On Hadoop 設計的一個基本原則是:將計算任務移動到資料所在的節點而不是反過來。這主要出於網路最佳化的目的,因為資料分布在不同的節點,如果移動資料那麼將會產生大量的低效的網路資料轉送。資料本地化一般分為三種:節點局部性 (Node Locality), 機架局部性 (Rack Locality) 和全域局部性 (Global Locality)。節點局部性是指將計算任務分配到資料所在的節點上,此時無需任何資料轉送,效率最佳。機架局部性是指將計算任務移動到資料所在的機架,雖然計算任務和資料分屬不同的計算節點,但是因為機架內部網路傳輸速度明顯高於機架間網路傳輸,所以機架局部性也是一種不錯的方式。其他的情況屬於全域局部性,此時需要跨機架進行網路傳輸,會產生非常大的網路傳輸開銷。

調度系統在進行任務調度時,應該儘可能的保證節點局部性,然後是機架局部性,如果以上兩者都不能滿足,調度系統也會通過網路傳輸將資料移動到計算任務所在的節點,雖然效能相對低效,但也比資源空置比較好。

為了實現資料本地化調度,調度系統會結合延遲調度演算法來進行任務調度。核心思想是優先將計算任務調度到資料所在的節點 i,如果節點 i 沒有足夠的計算資源,那麼等待幾秒鐘後如果節點 i 依然沒有計算資源可用,那麼就放棄資料本地化將該計算任務調度到其他計算節點。

3.2 減少中間結果的物化

在一個追求低延遲的 SQL On Hadoop 系統中,儘可能的減少中間結果的磁碟物化可以極大的提高查詢效能。 如,Hive 執行引擎採用 pull 擷取資料,其優點是可以進行細粒度的容錯,缺點是下遊的 MapReduce 必須等待上遊 MapReduce 完全將資料寫入到磁碟後才能開始 pull 資料。Presto 採用 push 方式擷取資料,資料完全以流的方式在不同 stage 之間進行傳輸,中間結果不需要物化到磁碟,從而使得 presto 具有非常高效的執行速度,缺點是不能支援細粒度的容錯。

(點擊放大映像)

圖 3push 和 pull

3.3 列儲存

傳統的關係儲存模型將一個元組的列連續儲存,即使只查詢一個列,也需要將整個元組讀取出來,可以發現,當查詢只有少量列時,效能非常低。

列儲存的思想是將元組垂直劃分為列族集合,每一個列族隔離儲存區 (Isolated Storage),列族可以退化為只僅包含一個列的平凡列族。當查詢少量列時,列儲存模型可以極大的減少磁碟 IO 操作,提高查詢效能。當查詢的列跨越多個列族時,需要將儲存在不同列族中列資料拼接成未經處理資料,由於不同列族儲存在不同的 HDFS 節點上,導致大量的資料跨越網路傳輸,從而降低查詢效能。因此在實際使用列族時,通常根據業務查詢特點,將頻繁訪問的列放在一個列族中。

在傳統的資料庫領域中,人們已經對列儲存進行了非常深刻的研究,並且很多研究成果已經被應用到工業領域,其中包括輕量級壓縮演算法,直接操作壓縮資料,延遲物化,向量化執行引擎。可是縱觀目前 SQL On Hadoop 系統,這些技術的應用仍然遠遠的落後於傳統資料庫,在最近的一些 SQL On Hadoop 中已經添加了向量化執行引擎,輕量級壓縮演算法,但是諸如直接操作壓縮資料,延遲解壓等技術還沒有被應用到 SQL on Hadop 系統。關於列儲存的更多內容可以參見 [20]。

列儲存壓縮

列儲存壓縮演算法具有如下特點:

壓縮比 列儲存模型具有非常高的壓縮比,通常可以達到 10:1,而行儲存壓縮比通常只有 4:1。 4:

(點擊放大映像)

圖 4 重量級壓縮演算法

輕量級壓縮演算法 (Leight-Weight Compression) 輕量級壓縮演算法是 CPU 友好的。行儲存模型只能使用 zip,lzo,snappy 等重量級壓縮演算法,這些演算法最大的缺點是壓縮和解壓縮速度比較慢,通常每秒只能解壓至多幾百兆資料。相反,列儲存模型不僅可以使用重量級壓縮演算法,還可以使用一些非常輕量級的壓縮演算法,比如 Run-length encode,Bit Vector。輕量級壓縮演算法不僅具有較好的壓縮比,而且還具有非常高的壓縮和解壓速度。目前在 ORC File 和 Parquet 儲存中,已經支援 Bit packing,Run-length enode,Dictionary encode 等輕量級壓縮演算法。

直接操作壓縮資料 (Operating Directly on Compressed Data) 當使用輕量級壓縮演算法時,可能無需解壓即可直接擷取計算結果。例如:Run Length Encode 演算法將連續重複的字元壓縮為字元個數和字元,比如 aaaaaabbccccaaaa 將被壓縮為 6a2b4c4a,其中 6a 表示有連續 6 個字元 a。現在假設一個某列包含上述壓縮的字串,當執行 select count(*) from table where columnA=’a’時,不需要解壓 6a2b4c4a,就能夠知道 a 的個數是 10。

需要注意的是,由於行儲存只能使用重量級壓縮演算法,所以直接操作壓縮資料不能被應用到行儲存。

延遲解壓 parquet 中的資料按Block Storage,每個Block Storage了最小值,最大值等輕量級索引,比如某個塊的最小值最大值分別是 100 和 120,這表明該塊中的任意一條資料都介於 100 到 120 之間,因此當我們執行 select column a  from table where  v>120 時,執行引擎可以跳過這個資料區塊,而不必將其解壓再進行資料過濾。相反,在行儲存中,必須將資料區塊完整的讀取到記憶體中,解壓,然後再進行資料過濾,導致不必要的磁碟讀取操作。

 

3.6 壓縮

一般情況下,壓縮 HDFS 中的檔案可以極大的提高查詢效能。壓縮能夠減少資料所佔用的儲存空間,減少磁碟 IO 的讀寫,提高資料處理速度,此外,壓縮還能夠減少網路傳輸量,提高網路傳輸速度。在 SQL On Hadoop 中,壓縮主要應用在 HDFS 中的資料來源,shuffle 資料,最終計算結果。

如果應用程式是 io-bound 的,那麼壓縮資料可以提高資料處理速度,因為壓縮後的資料變小了,所以可以增加資料讀寫速度。需要主要的是,壓縮演算法並不是壓縮比越高越好,壓縮率越高的演算法壓縮和解壓縮速度就越慢,使用者需要在 cpu 和 io 之間取得一個良好的平衡。例如 gzip2 擁有非常高的壓縮比,但是其壓縮和解壓縮速度卻非常慢,甚至可能超過資料未壓縮時的讀寫時間,因此沒有 SQL On Hadooop 系統使用 gzip2 演算法,目前在 SQL On Hadoop 系統中比較流行的壓縮演算法主要有:Snappy,Lzo,Glib。

如果應用程式是 cpu-bound 的,那麼選擇一個可以 splittable 的壓縮演算法是很重要的,如果一個檔案是 splittabe 的,那麼這個檔案可以被切分為多個可以並行讀取的資料區塊,這樣 MR 或者 Spark 在讀取檔案時,會為每一個資料區塊分配一個 task 來讀取資料,從而提高資料查詢速度。

3.7 向量化執行引擎

查詢執行引擎 (query execution engine) 是資料庫中的一個核心組件,用於將查詢計劃轉換為物理計劃,並對其求值返回結果。查詢執行引擎對資料庫系統效能影響很大,目前主要的執行引擎有如下四類:Volcano-style,Block-oriented processing,Column-at-a-time,Vectored iterator model。下面分別介紹這四種執行引擎。

Volcano-style, 最早的查詢執行引擎是 Volcano-style execution engine(火山執行引擎,火山模型),也叫做迭代模型 (iterator model),或者 one-tuple-at-a-time。在這種模型中,查詢計劃是一個由 operator 組成的 tree 或者 DAG,其中每一個 operator 包含三個函數:open,next,close。Open 用於申請資源,比如分配記憶體,開啟檔案,close 用於釋放資源,next 方法遞迴的調用子 operator 的 next 方法產生一個元組。圖 1 描述了 select id,name,age from people where age >30 的火山模型的查詢計劃,該查詢計劃包含 User,Project,Select,Scan 四個 operator,每個 operator 的 next 方法遞迴調用子節點的 next,一直遞迴調用到葉子節點 Scan operato,Scan Operator 的 next 從檔案中返回一個元組。

(點擊放大映像)

圖 3-4 火山模型 摘自文獻 [2,page 39]

火山模型的主要缺點是昂貴的解釋開銷 (interpretation overhead) 和低下的 CPU Cache 命中率。首先,火山模型的 next 方法通常實現為一個虛函數,在編譯器中,虛函數調用需要尋找虛函數表, 並且虛函數調用是一個非直接跳轉 (indirect jump), 會導致一次錯誤的 CPU 分支預測 (brance misprediction), 一次錯誤的分支預測需要十幾個周期的開銷。火山模型為了返回一個元組,需要調用多次 next 方法,導致昂貴的函數調用開銷。[] 研究表明,在採用火山執行模型的 MySQL 中執行 TPC-H Q1 查詢,僅有 10% 的時間用於真正的查詢計算,其餘的 90% 時間都浪費在解釋開銷 (interpretation overhead)。其次,next 方法一次只返回一個元組,元組通常採用行儲存, 3-5 Row Format,如果順序訪問第一列 1,2,3,那麼每次訪問都將導致 CPU Cache 命中失敗 (假設該行不能完全放入 CPU Cache 中)。如果採用 Column Format,那麼只有在訪問第一個值時才出現快取命中失敗,後續訪問 2 和 3 時都將快取命中成功, 從而極大的提高查詢效能。

(點擊放大映像)

圖 3-6 行儲存和列儲存

Block-oriented processing,Block-oriented processing 模型是對火山模型的一個改進,該模型一次 next 調用返回一批元組, 元組個數在 100-1000 不等,next 內部使用一個迴圈來處理這批元組。在圖 1 的火山模型中,Select operator next 方法可以如下實現:

def next():Array[Tuple]={  // 調用子節點的 next 方法,返回一個元組向量,該向量包含 1024 個元組  val tuples=child.next()  val result=new ArrayBuffer[Tuple]  for(i=0;i<tuples.length;i++){ 30="" age="" val="">30) result.append(tuples(i))  }  result// 返回結果}

Block-oriented processing 模型的優點是一次 next 返回多個元組,減少瞭解釋開銷,同時也被證明增加了 CPU Cache 的命中率,當 CPU 訪問元組中的某個列時會將該元組載入到 CPU Cache(如果該元組大小小於 CPU Cache 緩衝行的大小), 訪問後繼的列將直接從 CPU Cache 中擷取,從而具有較高的 CPU Cache 命中率,然而如果之訪問一個列或者少數幾個列時 CPU 命中率仍然不理想。該模型最大的一個缺點是不能充分利用現代編譯器技術,比如在上面的迴圈中,很難使用 SIMD 指令處理資料。

Column-at-a-time 模型,向量化執行的最早曆史可以追朔到 MonetDB[], 在 MonetDB 提出了一個叫做 Column-at-a-time 的查詢執行模型,該模型中每一次 next 調用返回一個或者多個列,每個列以數組形式返回。該模型優點是具有非常高的查詢效率,缺點是一個列資料需要被物化到記憶體甚至磁碟,導致很高的記憶體佔用和 io 開銷,同時資料不能放到 CPU Cache 中,導致較低的 CPU Cache 命中率。

Vectored iterator model,VectorWise 提出了 Vectored iterator model 模型,該模型是對 Column-at-a-time 的改進,next 調用不是返回完整的一個列,而是返回一個可以放到 CPU Cache 的向量。該模型避免了 Column-at-a-tim CPU Cache 命中率低的缺點。Vectored iterator model 最大的優點是可以使用運行時編譯器 (JIT) 動態產生更適合現代處理器的指令,比如 JIT 可以產生 SIMD 指令來處理向量。考慮 TPC-H Q1 查詢:SELECT l_extprice*(1-l_discount)*(1+l_tax) FROM lineitem。該 SQL 查詢的執行計畫如下:

(點擊放大映像)

其中 Project operator 的 next 方法可以如下實現 (scala 虛擬碼):

def next():Array[Tuple]={  val tuples=child.next()  var result=new ArrayBuffer[Int]  for(i=0;i<tuples.length;i++){ r="tuples.l_extprice*(1-tuple.l_discount)*(1+tuple.l_tax)" retult="" tuple="tuples(i)" val="">

近幾年,一些 SQL On Hadoop 系統引入了向量化執行引擎,比如 Hive,Impala,Presto,Spark 等,儘管其實現細節不同,但核心思想是一致的:儘可能的在一次 next 方法調用返回多條資料,然後使用動態代碼產生技術來最佳化迴圈,運算式計算從而減少解釋開銷,提高 CPU Cache 命中率,減少分支預測。

Impala 中的向量化執行引擎本質上屬於 Block-oriented processing,imapla 的每次 next 調用返回一批元組,這種模型仍然具有較低的 CPU Cache 命中率,同時也很難使用 SIMD 等指令進行最佳化,為了緩解這個問題,Impala 使用動態代碼產生技術,對於大迴圈,運算式計算等進行使用動態代碼產生來進行最佳化。

在 Spark2.0 中,實現了基於 Parquet 的向量化執行引擎 [12],該執行引擎屬於 Vectored iterator model,引擎在調用 next 方法時以列儲存格式返回一批元組,可以使用迴圈來處理該批元組。此外為了更充分的利用現代 CPU 特性,Spark 還支援整階段代碼產生技術,核心思想是將多個 operator 編譯到一個方法中,從而減少解釋開銷。

3.8 動態代碼產生

動態代碼產生一般和向量化執行引擎結合使用,因為向量執行引擎的 next 方法內部可以使用 for 迴圈來處理元組向量或者列向量,使用動態代碼產生技術可以在運行時對 next 方法產生更高效的執行代碼。研究證明向量化執行引擎和動態代碼產生可以減少解釋開銷 (interpretation overhead), 見文獻 [18],主要影響以下三個方面:

  • Select, 當 select 語句中包含複雜的運算式計算時,比如 avg,sum,count,select 的計算效能主要受 CPU Cache 和 SIMD 指令影響。當資料不能放到 CPU Cache 時,CPU 大部分時間都在等待資料從記憶體載入到 CPU Cache,因此當 CPU 執行計算所需的資料在 CPU Cache 中時可以極大的提高計算效能。一條 SIMD 指令可以同時計算多個資料,因此使用 SIMD 指令執行運算式計算可以提高計算效能。

  • where,與 Select 語句不同的是 Where 語句一般不需要複雜的計算,影響 where 效能更多的是分支預測。如果 CPU 分支預測錯誤,那麼之前的 CPU 流水線將全被清洗,一次 CPU 分支預測錯誤可能至少浪費十幾個指令周期的開銷。通過使用動態代碼產生技術,JIT 編譯器能夠自動的產生分支預測友好的指令。

  • Hash,hash 演算法影響 equal-join,group 的查詢效能,hash 演算法的 CPU Cache 命中率很低。[18] 描述了一種緩衝友好的 hash 演算法,可以顯著的提高 hash 計算效能。

動態代碼產生有兩種:C++ 系和 java 系。其中 C++ 系可以直接產生本機可執行二進位代碼,並且能夠產生高效的 SIMD 指令,例如 Impala 使用 C++ 實現查詢執行引擎,同時使用 LLVM 編譯器動態產生本機可執行二進位代碼,LLVM 可以產生 SIMD 指令對錶達式執行計算。Java 系利用反射機制動態產生 java 位元組碼,一般而言,不能充分利用 SIMD 指令進行最佳化,Spark 使用反射機制動態產生 java 位元組碼,通常很難直接利用 SIMD 進行運算式最佳化。此外在 Spark2.0 中所提供的整階段代碼產生 (Whole-Stage Code Generation) 技術也是動態代碼產生技術將多個 Operator 編譯成一個方法進行最佳化。

需要注意的是,動態代碼產生技術並不總是萬能藥,在中,impala 的動態代碼產生技術並沒有提高 TPC-DS Q42,Q52,Q55 的查詢速度,主要原因這些 SQL 陳述式的 SELECT 語句中並沒有什麼複雜的計算。

 

SQL On Hadoop 設計的一個基本原則是:將計算任務移動到資料所在的節點而不是反過來

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.