查詢(xún)改寫(xiě)與下推
查詢(xún)改寫(xiě)的一項(xiàng)重要目的是利用PolarDB-X的拆分信息來(lái)優(yōu)化執(zhí)行計(jì)劃,使得算子盡量下推,能夠達(dá)到提前過(guò)濾數(shù)據(jù)、減少網(wǎng)絡(luò)傳輸、并行執(zhí)行加速等效果。
背景信息
根據(jù)PolarDB-X SQL語(yǔ)句優(yōu)化的基本原則,可以下推更多的計(jì)算到存儲(chǔ)層MySQL上執(zhí)行。可下推計(jì)算主要包括:
JOIN連接。
過(guò)濾條件(如
WHERE
或HAVING
)。計(jì)算(如
COUNT
、GROUP BY
)。排序(如
ORDER BY
)。去重(如
DISTINCT
)。函數(shù)計(jì)算(如
NOW()
函數(shù))。子查詢(xún)。
通過(guò)explain optimizer + sql可以看到查詢(xún)改寫(xiě)的具體過(guò)程。
Project和Filter下推
一條SQL的執(zhí)行計(jì)劃在以下生成過(guò)程中,F(xiàn)ilter和Project被先后下推到LogicalView算子里面。Filter和Project下推可以達(dá)到提前過(guò)濾數(shù)據(jù)和減少網(wǎng)絡(luò)傳輸?shù)刃Ч?/p>
EXPLAIN OPTIMIZER select c_custkey,c_name from customer where c_custkey = 1;
其中c_custkey是分區(qū)鍵。
Limit和Sort下推
一條SQL的執(zhí)行計(jì)劃在如下生成過(guò)程中,Sort和Limit被先后下推到LogicalView算子里面。Sort和Limit下推可以達(dá)到提前過(guò)濾數(shù)據(jù),減少網(wǎng)絡(luò)傳輸、并行執(zhí)行加速和減少PolarDB-X內(nèi)存占用等效果。
EXPLAIN OPTIMIZER select * from customer order by c_name limit 10
Agg下推
一條SQL的執(zhí)行計(jì)劃在如下生成過(guò)程中,Agg被下推到LogicalView
算子里面。
Agg下推可以達(dá)到提前過(guò)濾數(shù)據(jù)、減少網(wǎng)絡(luò)傳輸、并行執(zhí)行加速和減少PolarDB-X內(nèi)存占用等效果。
EXPLAIN OPTIMIZER select count(*) from customer group by c_nationkey;
當(dāng)拆分鍵為c_nationkey情況:拆分鍵不為c_nationkey情況:
JoinClustering
當(dāng)有多個(gè)表執(zhí)行JOIN操作時(shí),PolarDB-X會(huì)通過(guò)JoinClustering的優(yōu)化技術(shù)將JOIN進(jìn)行重排序,將可下推的JOIN放到相鄰的位置,從而讓它可以被正常下推。示例如下:
假設(shè)原JOIN順序?yàn)閠2、t1、l2,經(jīng)過(guò)重排序之后,t2和l2的JOIN操作依然能下推到LogicalView。
EXPLAIN select t2.id from t2 join t1 on t2.id = t1.id join l2 on t1.id = l2.id;
返回執(zhí)行計(jì)劃信息如下:
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下推需要滿(mǎn)足以下條件:
t1與t2表的拆分方式一致(包括分庫(kù)鍵、分表鍵、拆分函數(shù)、分庫(kù)分表數(shù)目)。
JOIN條件中包含t1,t2表拆分鍵的等值關(guān)系。
此外,任意表JOIN廣播表總是可以下推。
EXPLAIN OPTIMIZER select * from t1, t2 where t1.id = t2.id;
一條SQL的執(zhí)行計(jì)劃在如下生成過(guò)程中,JOIN下推到LogicalView算子里面。可以達(dá)到計(jì)算離存儲(chǔ)更近,并行執(zhí)行加速的效果。
子查詢(xún)下推
一條SQL的執(zhí)行計(jì)劃在如下生成過(guò)程中,子查詢(xún)下推到LogicalView
算子里面。子查詢(xún)下推可以達(dá)到計(jì)算離存儲(chǔ)更近,并行執(zhí)行加速的效果。
子查詢(xún)會(huì)先被轉(zhuǎn)換成
Semi Join
或Anti Join
。如果滿(mǎn)足JOIN下推的判斷條件,就會(huì)將
Semi Join
或Anti Join
下推至LogicalView
。下推后的
Semi Join
或Anti Join
會(huì)被還原為子查詢(xún)。
EXPLAIN OPTIMIZER select * from t1 where id in (select id from t2);