查詢改寫的一項重要目的是利用PolarDB-X的拆分資訊來最佳化執行計畫,使得運算元盡量下推,能夠達到提前過濾資料、減少網路傳輸、並存執行加速等效果。
背景資訊
根據PolarDB-X SQL語句最佳化的基本原則,可以下推更多的計算到儲存層MySQL上執行。可下推計算主要包括:
JOIN串連。
過濾條件(如
WHERE
或HAVING
)。計算(如
COUNT
、GROUP BY
)。排序(如
ORDER BY
)。去重(如
DISTINCT
)。Function Compute(如
NOW()
函數)。子查詢。
通過explain optimizer + sql可以看到查詢改寫的具體過程。
Project和Filter下推
一條SQL的執行計畫在以下產生過程中,Filter和Project被先後下推到LogicalView運算元裡面。Filter和Project下推可以達到提前過濾資料和減少網路傳輸等效果。
EXPLAIN OPTIMIZER select c_custkey,c_name from customer where c_custkey = 1;
其中c_custkey是分區鍵。
Limit和Sort下推
一條SQL的執行計畫在如下產生過程中,Sort和Limit被先後下推到LogicalView運算元裡面。Sort和Limit下推可以達到提前過濾資料,減少網路傳輸、並存執行加速和減少PolarDB-X記憶體佔用等效果。
EXPLAIN OPTIMIZER select * from customer order by c_name limit 10
Agg下推
一條SQL的執行計畫在如下產生過程中,Agg被下推到LogicalView
運算元裡面。
Agg下推可以達到提前過濾資料、減少網路傳輸、並存執行加速和減少PolarDB-X記憶體佔用等效果。
EXPLAIN OPTIMIZER select count(*) from customer group by c_nationkey;
當拆分鍵為c_nationkey情況:拆分鍵不為c_nationkey情況:
JoinClustering
當有多個表執行JOIN操作時,PolarDB-X會通過JoinClustering的最佳化技術將JOIN進行重排序,將可下推的JOIN放到相鄰的位置,從而讓它可以被正常下推。樣本如下:
假設原JOIN順序為t2、t1、l2,經過重排序之後,t2和l2的JOIN操作依然能下推到LogicalView。
EXPLAIN select t2.id from t2 join t1 on t2.id = t1.id join l2 on t1.id = l2.id;
返回執行計畫資訊如下:
Project(id="id")
HashJoin(condition="id = id AND id = id0", type="inner")
Gather(concurrent=true)
LogicalView(tables="t2_[0-3],l2_[0-3]", shardCount=4, sql="SELECT `t2`.`id`, `l2`.`id` AS `id0` FROM `t2` AS `t2` INNER JOIN `l2` AS `l2` ON (`t2`.`id` = `l2`.`id`) WHERE (`t2`.`id` = `l2`.`id`)")
Gather(concurrent=true)
LogicalView(tables="t1", shardCount=2, sql="SELECT `id` FROM `t1` AS `t1`")
JOIN下推
JOIN下推需要滿足以下條件:
t1與t2表的拆分方式一致(包括分庫鍵、分表鍵、拆分函數、分庫分表數目)。
JOIN條件中包含t1,t2表拆分鍵的等值關係。
此外,任意表JOIN廣播表總是可以下推。
EXPLAIN OPTIMIZER select * from t1, t2 where t1.id = t2.id;
一條SQL的執行計畫在如下產生過程中,JOIN下推到LogicalView運算元裡面。可以達到計算離儲存更近,並存執行加速的效果。
子查詢下推
一條SQL的執行計畫在如下產生過程中,子查詢下推到LogicalView
運算元裡面。子查詢下推可以達到計算離儲存更近,並存執行加速的效果。
子查詢會先被轉換成
Semi Join
或Anti Join
。如果滿足JOIN下推的判斷條件,就會將
Semi Join
或Anti Join
下推至LogicalView
。下推後的
Semi Join
或Anti Join
會被還原為子查詢。
EXPLAIN OPTIMIZER select * from t1 where id in (select id from t2);