W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Mycat2在1.17開(kāi)始正式支持JoinClustering
,該名字來(lái)自于PolarDB-X
的JoinClustering
.它對(duì)分庫(kù)分表類(lèi)數(shù)據(jù)庫(kù)的join
下推至關(guān)重要.Mycat2對(duì)其理解后進(jìn)行開(kāi)源實(shí)現(xiàn).
它是SQL重寫(xiě)技術(shù),優(yōu)化目標(biāo)是生成更優(yōu)的存儲(chǔ)節(jié)點(diǎn)執(zhí)行的SQL,使更多Join
運(yùn)算在存儲(chǔ)節(jié)點(diǎn)運(yùn)算,大大減少M(fèi)ycat2的運(yùn)算.它是基于Join Reorder
技術(shù)進(jìn)行構(gòu)建的.Mycat2的SQL重寫(xiě)器在遇到不能應(yīng)用兩表下推規(guī)則(任意表+全局表),再判斷是否是inner join
,則啟動(dòng)代價(jià)優(yōu)化器,使用
JOIN ASSOCIATE: (a JOIN b) JOIN c) → (a JOIN (b JOIN c))
JOIN COMMUTE:``(a JOIN b)→(b JOIN a)
JOIN PUSH THROUGH JOIN: (A join B) join C ``→`` (A join C) join B
作為Join Reorder規(guī)則 然后在上述規(guī)則作用下對(duì)新的join關(guān)系表達(dá)式進(jìn)行ER表規(guī)則應(yīng)用
比如
t2(分片表),t1(單表),t3(分片表),t2和t3屬于父子表關(guān)系,具有相同的數(shù)據(jù)分布
select t2.id from t2 join t1 on t2.id = t1.id join t3 on t1.id = t3.id;
此處的id實(shí)際上它們的值是相同的,輸出值實(shí)際上可以來(lái)自三個(gè)表t2
,t1
,t3
在沒(méi)有JoinClustering的情況
t2 join t1 join t3
,因?yàn)閠2和t3沒(méi)有相鄰(因?yàn)閠1的阻隔),導(dǎo)致無(wú)法應(yīng)用ER表下推規(guī)則
在有JoinClustering的情況
代價(jià)優(yōu)化器會(huì)交換 表的順序,生成t2 join t3 join t1
并成功使用ER表下推規(guī)則
1.17版本基于COMMUTE
規(guī)則實(shí)現(xiàn),存在優(yōu)化十分耗時(shí)的問(wèn)題,因?yàn)樗乃阉骺臻g大(混合了邏輯優(yōu)化與物理優(yōu)化),雖然使用了執(zhí)行計(jì)劃管理可以手動(dòng)持久化已有的執(zhí)行計(jì)劃,省去優(yōu)化階段,這樣可以暫時(shí)解決問(wèn)題,所以在1.18對(duì)Join
的優(yōu)化進(jìn)一步探索,實(shí)現(xiàn)了基于MultiJoin
的reorder
,它在規(guī)則優(yōu)化器就可以使用,基于一定規(guī)則,把多個(gè)join
轉(zhuǎn)換成MutilJoin
來(lái)表達(dá),然后在MutilJoin
的形式下進(jìn)行邏輯優(yōu)化
1.17的JoinClustering階段
Logical RBO →View RBO→ JoinClustering CBO→Physical CBO
JoinClustering
實(shí)際上就是一個(gè)獨(dú)立的CBO
階段
1.18的JoinClustering階段
Logical RBO →JoinClustering RBO→Logical RBO →View RBO→Physical CBO
多個(gè)join轉(zhuǎn)換成多個(gè)Multi join.因?yàn)閖oin不同的樹(shù)形,我們暫時(shí)只關(guān)注inner join
的這一種
A JOIN B → MJ(A, B)A JOIN B JOIN C → MJ(A, B, C)
進(jìn)行JoinClustering
的規(guī)則.與一般的Join Reorder
不同,Join Reorder
關(guān)注執(zhí)行器層面跑得更快更好,它們關(guān)注統(tǒng)計(jì)信息的行數(shù),選擇性的信息.而在分庫(kù)分表數(shù)據(jù)庫(kù)中,JoinClustering
關(guān)注把相同存儲(chǔ)節(jié)點(diǎn)相同的表靠近在一起,這樣可以把更多join
運(yùn)算在存儲(chǔ)節(jié)點(diǎn)中進(jìn)行,所以它關(guān)注輸入的關(guān)系表達(dá)式的順序.
input reorder
對(duì)輸入的關(guān)系表達(dá)式進(jìn)行排序,排序的依據(jù)是View
的數(shù)據(jù)分布,局部來(lái)說(shuō),把可以下推的表相鄰排列.整體來(lái)說(shuō),把可以下推的表往左排,不可以下推的表往右排.如果發(fā)現(xiàn)排序后,輸入的順序沒(méi)有改變,則優(yōu)化結(jié)束.
field reorder 因?yàn)檩斎氲年P(guān)系表達(dá)式順序改變了,所以條件表達(dá)式對(duì)輸入字段的引用需要重新計(jì)算,調(diào)整正確即可.然后我們對(duì)條件進(jìn)行的字段一些簡(jiǎn)化.目的是調(diào)整字段的值的依賴.
應(yīng)用傳遞性(前提是等價(jià)關(guān)系,不滿足等價(jià)關(guān)系的條件表達(dá)式不進(jìn)行優(yōu)化)
(a.id = b.id) and (b.id = c.id)→(a.id = b.id) and (a.id = c.id)
根據(jù)輸入的關(guān)系表達(dá)式的順序?qū)ψ侄芜M(jìn)行排序
順序:a
,c
,b
(a.id = b.id) and (b.id = c.id)→(a.id = c.id) and (a.id = b.id)
最終得到
a join c : (a.id = c.id)
a join b: (a.id = b.id)
→
(a join c join b):(a.id = c.id) and (a.id = b.id)
field adjust
因?yàn)閷?duì)輸入順序改變了,所以join
的字段類(lèi)型順序也改變了,所以添加一個(gè)Project
表達(dá)式把新生成的MutilJoin
的字段信息投影至與原表達(dá)式相同的類(lèi)型.
最后,使用該規(guī)則把MULTI_JOIN
還原成JOIN
.
使用Multi join
可以僅僅關(guān)注邏輯優(yōu)化中的join
節(jié)點(diǎn)部分進(jìn)行轉(zhuǎn)換,使用幾個(gè)邏輯優(yōu)化規(guī)則就可以進(jìn)行優(yōu)化,把優(yōu)化范圍限制在Multi join
節(jié)點(diǎn)的范圍之內(nèi),大大減少了優(yōu)化耗時(shí).
邏輯SQL:
select * from db1.sharding s join db1.global g ?on s.id = g.id join ?db1.er e ?on ?e.id = g.id
生成執(zhí)行SQL模板
MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]
`SELECT * ?FROM db1.sharding INNER JOIN db1.global ON (`sharding`.`id` = `global`.`id`) ? ? ?INNER JOIN db1.er ON (`global`.`id` = `er`.`id`)`
邏輯SQL:
select t2.id from db1.sharding t2 join db1.normal t1 on t2.id = t1.id join db1.er l2 on t1.id = l2.id
生成執(zhí)行SQL模板
MycatProject(id=[$0]) ? ?
MycatHashJoin(condition=[=($0, $1)], joinType=[inner]) ? ? ?
?MycatView(distribution=[shardingTables=db1.sharding,db1.er]) ? ? ?
?MycatView(distribution=[normalTables=db1.normal]) ?
`
SELECT `sharding`.`id` ?FROM db1.sharding ? ? ?INNER JOIN db1.er ON (`sharding`.`id` = `er`.`id`)`
...
`(SELECT `sharding_0`.`id` ? ? FROM db1_0.sharding_0 ? ? ? ? INNER JOIN db1_0.er_0 ON (`sharding_0`.`id` = `er_0`.`id`) ? ? UNION ALL ? ? SELECT `sharding_1`.`id` ? ? FROM db1_0.sharding_1 ? ? ? ? INNER JOIN db1_0.er_1 ON (`sharding_1`.`id` = `er_1`.`id`)))`
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: