全部產品
Search
文件中心

ApsaraDB for SelectDB:Join最佳化

更新時間:Jul 06, 2024

本文介紹ApsaraDB for SelectDB中針對Join操作所設計的一系列最佳化方案,以及基於此給出的Join最佳化參考,協助您提升查詢速度。

物理運算元支援

SelectDB支援如下兩種物理Join運算元,用於實現單機引擎中資料進行Join的處理過程。

  • Hash Join:在右表上根據等值Join列建立雜湊表,左表流式的利用雜湊表進行Join計算,這個運算元只適用於等值Join。

  • Nest Loop Join:通過兩個for迴圈進行Join過程處理。它適用的情境是不等值的Join,例如大於小於或者是需要求笛卡爾積的情境。它是一個通用的Join運算元,但是效能表現差。

Shuffle方式概述

作為分布式的MPP資料庫,SelectDB在Join的過程中需要先進行資料的Shuffle,然後才調用物理運算元進行處理。SelectDB現階段支援4種Shuffle方式,以下舉例說明。

下述樣本將對錶S和表R進行Join,其中N表示參與Join計算的節點的數量,T則表示表的記錄數。

  • Broadcast Join

    它要求把R表的全量的資料都發送到S表上,即每一個參與Join的節點,它都擁有R表全量的資料,也就是T(R)。這個Shuffle方式較為通用,同時能夠支援Hash Join和Nest loop Join。它的網路開銷是N*T(R)

    S表資料不移動,R表資料發送到S表資料的掃描節點。

  • Shuffle Join

    當進行Hash Join時,可以通過Join列計算S表和R表相應資料的雜湊值,把相同雜湊值的資料被分發到分布式系統中的同一個節點,利用分布式系統加速Join查詢。它的網路開銷是T(S)+T(R),但它只能支援Hash Join,因為它根據Join的條件計算分桶。

    S表和R表資料根據分區計算,計算的結果發送到不同的分區節點上。

  • Bucket Shuffle Join

    SelectDB的表資料本身是通過雜湊計算分桶的,所以就可以利用表本身的分桶列的性質來進行Join資料的Shuffle。例如兩張表;表S和表R需要做Join,並且Join列是表S的分桶列,那麼表S的資料其實可以不需要移動,通過移動分發表R的資料就可以完成Join的計算。

    它的網路開銷是T(R),相當於只Shuffle表R的資料就可以完成Join。有關Bucket Shuffle Join使用的更多細節,詳見Bucket Shuffle Join

    表S資料不移動,表R資料根據分區計算的結果發送到S表掃表的節點

  • Colocation Join

    對於多個相關聯的表,在建表時確保表的資料分區數量一致,相同Hash分桶在分布式系統中的分布一致,那麼實際查詢時就可以跳過資料的Shuffle過程,直接進行Join計算,提升查詢效能。Colocation Join詳情,請參見Colocation Join

    資料已經預先分區,不需要考慮網路開銷,直接在本地進行Join計算。

四種Shuffle方式對比如下。

Shuffle方式

網路開銷

物理運算元

適用情境

BroadCast

N*T(R)

Hash Join/Nest Loop Join

通用

Shuffle

T(S)+T(R)

Hash Join

通用

Bucket Shuffle

T(R)

Hash Join

Join條件中存在左表的分布式列,且左表在執行時只使用單分區的資料

Colocation

0

Hash Join

Join條件中存在左表的分布式列,且左右表同屬於一個Colocate Group

上述這4種Shuffle方式的靈活度按照從高到低排列,對資料分布的要求越來越嚴格,但Join計算的效能也逐級提高。

Runtime Filter最佳化

Runtime Filter在查詢規劃時動態產生,由HashJoin運算元(對應查詢Explain/Profile中的HashJoinNode)中將Join過程中的右錶轉換為過濾條件,下推給資料掃描運算元(對應查詢Explain/Profile中的ScanNode),然後在左表掃描過程中進行裁剪過濾。這種方式大幅降低查詢過程中的資料讀取和計算,提升了查詢效能。Runtime Filter詳情,請參見Runtime Filter

Join Reorder

在多表Join的情境下,Join的順序對整個Join查詢的效能影響很大。

例如有三張表Join,如下圖所示。其中ScanA,ScanB,ScanC代表表A,B,C根據查詢條件進行完初步的Scan後得到的資料。

在上圖的左側,表A和表B的Scan先進行Join,產生2000行中間結果,然後與表C的Scan再進行Join計算。

在右側,Join的順序經過了調整。把表A的Scan先與表C的Scan Join,產生的中間結果只有100,然後再與表B的Scan Join計算。最終的Join結果是一樣的,但是它產生的中間結果有20倍的差距,因此會產生一個很大的效能差距。

SelectDB目前支援基於規則的Join Reorder演算法。它的邏輯如下。

  • 建議優先選擇將大表與小表進行Join操作,以便產生儘可能小的中間結果。

  • 將有條件的Join表寫在查詢語句中的靠前位置,盡量讓有條件的Join表進行過濾。

  • Hash Join的優先順序高於Nest Loop Join,因為Hash Join的執行速度明顯快於Nest Loop Join。

Join調優方法

Join調優的方法大致按照如下步驟進行。

  1. 利用SelectDB本身提供的Profile來定位查詢的瓶頸。Profile會記錄SelectDB整個查詢中的各種資訊,這對進行效能調優非常重要。

  2. 深入瞭解SelectDB的Join機制,瞭解其原理,才能深刻分析其效能較慢的原因。

  3. 利用會話變數來修改Join操作的一些行為,以實現Join操作的最佳化。

  4. 查看Query Plan去分析這個調優是否生效。

上述4個步驟描述了標準的Join調優流程。如果在完成了上述流程後仍未見效果,可能需要重新編寫Join語句,或者調整資料分布並重新檢查整個資料分布是否合理,包括手動調整查詢所用的Join語句。然而,這種方式的所花費的成本相對較高,因此在上述方法無效的情況下才需要進一步分析。

Join調優建議

SelectDB Join最佳化調優的一些建議如下。

  • 進行Join的時候,盡量選擇同類型或者簡單類型的列,同類型列可以減少資料Cast,簡單類型本身Join計算就很快。

  • 盡量選擇Key列進行Join,原因參見Runtime Filter。Key列在延遲物化上有較好的效果。

  • 盡量讓大表之間的Join以Colocation的方式進行。因為大表之間進行Join會帶來很大的網路開銷,會使得Shuffle的代價急劇升高。

  • 合理使用Runtime Filter。它在Join過濾率高的情境下效果非常顯著,但它同時具有一定副作用,需要根據具體的SQL的粒度做開關。

  • 涉及到多表Join時,需要去判斷Join的合理性。盡量保證左表為大表,右表為小表。這種情境下,Hash Join會優於Nest Loop Join。必要的時可以通過SQL Rewrite,利用Hint去調整Join的順序。