本文描述的設計細節(jié),大部分已經(jīng)實現(xiàn),有小部分沒有完全實現(xiàn)。
Mycat2減少使用人類理解編寫的SQL解析路由和基于經(jīng)驗制作的查詢引擎的思路來實現(xiàn)查詢引擎,取而代之,使用基于關(guān)系表達式轉(zhuǎn)換SQL的思路以支持更多甚至是標準SQL,MySQL語法的SQL。使用Java生態(tài)Apache Calcite項目,改造成以接收MySQL方言的SQL,翻譯該SQL變成Mycat算子和查詢物理庫的SQL。該引擎在設計上可以脫離網(wǎng)絡層獨立運行。
Mycat2使用calcite作為優(yōu)化器實現(xiàn),優(yōu)化有四個階段。
第一階段Mycat把MySQL語法的SQL編譯成語法抽象樹,并進一步把它編譯成邏輯關(guān)系表達式,值得注意的是,輯MySQL方言元素以Hint或者特征的形態(tài)保存在表達式內(nèi),而不會以表達式表示。
第二階段是基于規(guī)則改寫邏輯關(guān)系表達式,把可以下推到Mysql關(guān)系表達式轉(zhuǎn)換以特殊的節(jié)點保存,該節(jié)點最終執(zhí)行的時候以SQL表示運算。
第三階段是使用基于代價的優(yōu)化方法把未能下推的,需要在Mycat里運算的算子選擇物理算子。
第四階段則進一步把物理算子翻譯成對應的執(zhí)行計劃,執(zhí)行計劃是以樹節(jié)點表示的執(zhí)行樹,與執(zhí)行流程是對應的,而且是有狀態(tài)的.而上述的關(guān)系表達式是不可變對象,無狀態(tài)的。上述有微妙的關(guān)系,算子與執(zhí)行器沒有嚴格的對應關(guān)系,它們的樹形狀并不是對應的,但是有轉(zhuǎn)換程序把算子生成執(zhí)行器。
在Mycat2開發(fā)的歷史中,使用calcite實現(xiàn)的查詢引擎有兩個版本,其技術(shù)特征如下。
該設計最大程度依賴calcite現(xiàn)有功能,而且下推的方法比較直觀,但是僅僅在邏輯關(guān)系表達式層面做處理,未能深入更深入的優(yōu)化,需要編寫更多規(guī)則實現(xiàn),而且對于一些情況難以控制關(guān)系表達式的改寫,另外由于開發(fā)時候?qū)儆谠缙陔A段,未能實現(xiàn)Mycat自研的執(zhí)行器所以未能使用執(zhí)行成本優(yōu)化,使用calcite的內(nèi)置執(zhí)行器實現(xiàn)執(zhí)行。它在用戶測試以及使用中發(fā)現(xiàn)使用Calcite的解釋器執(zhí)行器執(zhí)行效率較低,而代碼生成器的執(zhí)行器難以理解調(diào)試。所以開始制作第二代執(zhí)行引擎。
開發(fā)第二代查詢引擎的過程中,嘗試了很多方案,包括移植1.6的查詢引擎,自研SQL編譯成不支持關(guān)聯(lián)子查詢的表達式樹并自研執(zhí)行器,經(jīng)過多次方案和測試,保留自研執(zhí)行器。因為難以界定簡單sql與復雜sql,可能導致多次編譯,所以拋棄自研的SQL編譯器。為了實現(xiàn)執(zhí)行器,深入使用Calcite,實現(xiàn)MycatRel,把關(guān)系表達式轉(zhuǎn)換為Mycat自研的關(guān)系表達式類,在此之上再轉(zhuǎn)換成執(zhí)行器。執(zhí)行器保留Caclite的表達式編譯器,使用代碼生成技術(shù),對標量表達式生成java代碼,然后動態(tài)編譯成類,然后加載為對象,執(zhí)行。對于關(guān)系表達式,則是自己實現(xiàn)執(zhí)行器,而不使用代碼生成方案,雖然效率有所降低,但是便于調(diào)試,因為考慮到之后可能有替換執(zhí)行器的可能,所以暫時無需優(yōu)化至極致。
然后為了實現(xiàn)對物理節(jié)點的SQL可控,研究關(guān)系表達式與SQL的生成規(guī)則,實現(xiàn)了有效的關(guān)系表達式下推判斷器。然后為了對已排序的節(jié)點進行規(guī)則優(yōu)化,引入排序特征傳播(相比之下,手動的HBT就比較難表達這些信息了,Hint可能是一個方向)。后來再參考阿里DRDS的參數(shù)化思路,實現(xiàn)參數(shù)化功能原型.最后為了結(jié)合第一代查詢引擎的任意分配配置,基于名字而不是基于下標的分表映射方案(第二代原始設計是基于下標指向拆分的物理表),重新引入第一代查詢引擎的思路,基于規(guī)則判斷,對于復雜的SQL,邏輯表編譯成物理表再優(yōu)化。這樣就完成了第二代查詢引擎。
引入?yún)?shù)化
理想的參數(shù)化就是把sql中的直接量提取出來,用參數(shù)化標記?替代,sql就變成參數(shù)化模板,把SQL中部分常量以?替換,形成參數(shù)化模板與參數(shù)值,以該參數(shù)化模板為key,查詢緩存是否已經(jīng)有物理算子或者已經(jīng)解析好的SQL抽象語法樹,也就說緩存的對象有兩種.對于物理算子,一個參數(shù)化模板可能對應多種物理算子,這是因為使用的優(yōu)化方法不同導致的結(jié)果.Mycat會使用執(zhí)行代價的物理算子來執(zhí)行。上面說得很理想,但是還是有限制的,在Mycat2里面,暫時不會對offset,limit,以及select item的值進行參數(shù)化。前者會影響生成物理算子,因為行數(shù)對算子選擇有影響。后者會影響結(jié)果集類型的生成。
參數(shù)化的MycatView
MycatView這個名字參考阿里DRDS的View算子,在Mycat2第一代引擎有類似的東西,叫做MycatTransientSQLTableScan,一種臨時的TableScan,它以sql字符串和數(shù)據(jù)源信息來構(gòu)造。而MycatView使用關(guān)系表達式與數(shù)據(jù)分布來表示,數(shù)據(jù)分布包含兩類,一種是具體的,他們就是已經(jīng)包含具體物理表的信息。一種是需要賦以參數(shù)值才可以得到具體信息,如果不,只能得到全表掃描信息,也就是說,MycatView計算物理表可以是惰性計算的。理想情況下,一個參數(shù)化的關(guān)系表達式,不同的參數(shù)值能影響它掃描分表數(shù)量。
一對多的MycatView
一般來說,MycatView保存的關(guān)系表達式是關(guān)于邏輯表的,而物理表信息以數(shù)據(jù)分布來表示。在分表情況下,一般來說,一個邏輯表對應多個物理表。在實現(xiàn)了參數(shù)化后,關(guān)于邏輯表的關(guān)系表達式成為了模板的存在,(它也包含參數(shù)標記?)在生成執(zhí)行計劃的時候,應用參數(shù)值,使邏輯表的MycatView擴展成多個分片物理表的關(guān)系表達式。換句話說,使用MycatView‘概括’多個分片節(jié)點的關(guān)系表達式,即使用一個分片表達式與多個分片節(jié)點信息,減少規(guī)則重寫表達式存在多個重復的改寫消耗,設想,如果有100個物理表,使用邏輯表編譯成物理表的方法,如果涉及對這些物理表的關(guān)系表達式改寫則要進行100次,而使用MycatView‘概括’只需1次。
具體的MycatView
而對于復雜的sql,Mycat可能會選擇使用物理表擴展的方法來優(yōu)化,這是因為分片條件對算子的形狀影響很大,對于這個情況,mycat僅僅緩存sql抽象語法樹,并在規(guī)則優(yōu)化階段就應用參數(shù)值,把邏輯表擴展成物理表。
過早優(yōu)化的MycatView
對于簡單sql,如果在規(guī)則優(yōu)化階段已經(jīng)得到MycatView,則無需進行物理算子優(yōu)化,直接生成執(zhí)行計劃,因為MycatView本身就是物理算子。與第一代查詢引擎相比,Mycat2自研了執(zhí)行器,執(zhí)行器與物理算子存在多對一的關(guān)系,例如就算Sort節(jié)點被代價優(yōu)化器選擇為MemSort,Mycat在生成執(zhí)行器的時候發(fā)現(xiàn)帶有l(wèi)imit和排序字段會編譯成TopN執(zhí)行器,而發(fā)現(xiàn)只有l(wèi)imit時候則會僅限制行數(shù)量。
參數(shù)化與預處理語句
在一般的預處理語句,用戶提供預處理語句,預處理語句通過特殊的語法或者客戶端使用特殊通訊協(xié)議把預處理語句發(fā)送到數(shù)據(jù)庫,然后數(shù)據(jù)庫返回指向該預處理語句的句柄.當客戶端要執(zhí)行這個預處理語句的時候,通過對?賦值,然后交給數(shù)據(jù)庫執(zhí)行.預處理語句中的?是一種參數(shù)標記,一般來說,參數(shù)是直接量,它們的參數(shù)類型可以根據(jù)SQL的語法,語義推導出來出來,但是不一定完全是確定的,因為實際參數(shù)類型取決于實際值.對于整個SQL的結(jié)果集類型,是根據(jù)Select Item表達式的類型推導出來的.如此來說,整個結(jié)果集的類型實際上也是不確定的.
外部參數(shù)化
對于客戶端相關(guān)的預處理語句參數(shù),在Mycat的查詢引擎中稱為外部參數(shù),它們就是直接量.對于把沒有?參數(shù)化標記的SQL轉(zhuǎn)換成帶有?和參數(shù)值的SQL對象,這個過程稱為參數(shù)化.在這里我們把外部參數(shù)相關(guān)的參數(shù)化叫做外部參數(shù)化。
內(nèi)部參數(shù)化
在SQL層面上,不同的SQL產(chǎn)生的邏輯關(guān)系表達式可能是相似的.把TableScan,Values的算子去掉,它們是相同的。如果把關(guān)系表達式也用?來表示,則稱為內(nèi)部參數(shù)化,如果以SQL模板來表示內(nèi)部化參數(shù)則表名也是?。這樣的SQL模板更為通用。Mycat暫時沒有顯式實現(xiàn)這種方式但有使用這種思路。
不參數(shù)化的直接量
關(guān)聯(lián)子查詢
Calcite在編譯SQL的時候會解子查詢,使用join,SemiJoin,Agg替代關(guān)聯(lián)子查詢,最后還有小部分子查詢不能消去,以Correlate的形式存在,對于這個算子,Mycat2的執(zhí)行器暫時不支持(如果以后這種sql確實有很多需求就考慮支持)。涉及到Correlate的關(guān)系表達式,要求它的執(zhí)行器的輸入直接具備引用外部上下文變量的功能,具體就是表達式編譯的時候,生成的表達式要求支持變量來自其所在的關(guān)系表達式之上的Correlate節(jié)點。
內(nèi)置表
Mycat2支持自定義表數(shù)據(jù)的來源,具體要自定義開發(fā)。暫時能確定的下推的接口是Filter,Project,Limit,Sort。而對于元表相關(guān)的,暫時沒有實現(xiàn)下推接口的計劃。
RBO(基于規(guī)則的優(yōu)化)
SQL經(jīng)過解析轉(zhuǎn)換成抽象語法樹,然后進行語法級別的規(guī)范化(基于SQL改寫,化簡一些稍復雜表達式到統(tǒng)一語法),然后基于語法節(jié)點推導對應的值類型.并驗證類型轉(zhuǎn)換,最后轉(zhuǎn)換成關(guān)系表達式。然后關(guān)系表達式進行優(yōu)化階段。Mycat2首先進行RBO,使用自定義的規(guī)則,對關(guān)系表達式進行優(yōu)化。RBO的實現(xiàn)各式各樣,在Mycat2的RBO實現(xiàn)中,使用基于Calcite的Hep優(yōu)化器,它對規(guī)則依次應用,直到關(guān)系表達式不再變化,即優(yōu)化結(jié)束。另一方面,Mycat2也有直接使用前序遍歷結(jié)合后序遍歷關(guān)系表達式樹直接進行改寫的實現(xiàn)方式,但是最后還是把這種實現(xiàn)方式直接‘嵌入’到Hep優(yōu)化器之內(nèi)進行。這樣實現(xiàn)的好處是,1.可以利用Hep優(yōu)化器的驗證校驗節(jié)點類型的功能,檢查錯誤。2.統(tǒng)一優(yōu)化規(guī)則的實現(xiàn)方式,即統(tǒng)一使用Calcite的框架實現(xiàn),因此規(guī)則使用上不區(qū)分Hep優(yōu)化器還是volcano優(yōu)化器。但是也會導致一些問題,RBO在優(yōu)化器遇上矛盾的規(guī)則的時候,可能會導致規(guī)則之間相互優(yōu)化,導致不能停機(到達優(yōu)化限制次數(shù))。最后,Mycat不把RBO的規(guī)則完全放在CBO中,是為了減少CBO中搜索的優(yōu)化空間過大,Mycat2主要使用場景是TP場景,對響應及時性要求很高,而優(yōu)化關(guān)系表達式是需要耗費不確定的時間,為了減少優(yōu)化時間,所以存在RBO優(yōu)化階段。
總體來說,通過RBO應用一部分邏輯關(guān)系表達式優(yōu)化的規(guī)則,然后CBO再應用物理算子規(guī)則。
CBO(基于成本的優(yōu)化)
Mycat2的CBO主要是完成邏輯關(guān)系表達式,選擇物理算子,轉(zhuǎn)換到物理算子的任務。Mycat2在TP場景的設計上,CBO并沒有改寫關(guān)系表達式樹的形態(tài),僅僅是邏輯關(guān)系表達式到物理關(guān)系表達式的一對一映射。CBO通過獲得葉子節(jié)點(數(shù)據(jù)源)的信息,一般是指行數(shù),然后根據(jù)窮舉使用物理算子的計算代價規(guī)則,生成每個算子的執(zhí)行代價(一般是行數(shù),cpu代價,內(nèi)存代價),以及物理算子之間的要求,比如一些算子對后置節(jié)點具有排序要求。綜合這些信息,使用動態(tài)規(guī)劃算法,最后組裝出使用物理算子表達的關(guān)系表達式。CBO需要統(tǒng)計組件支持。
生成執(zhí)行器
在生成執(zhí)行器的階段,要求關(guān)系表達式具有完全的信息,例如,參數(shù)化之后關(guān)系表達式,不提供其參數(shù)值,這肯定是不能執(zhí)行的。生成器根據(jù)參數(shù)值以及必要的上下文,把還沒有確定具體分片的View轉(zhuǎn)換成具體的View,并收集涉及參與使用數(shù)據(jù)源。最后還適配不同的執(zhí)行工具,比如proxy的,只支持獲取單一數(shù)據(jù)源的實現(xiàn)。jdbc的,涉及多個分片的。
由于Mysql本身對于一些語法執(zhí)行效率不高,Mycat在第一代查詢引擎與第二代查詢引擎都有選擇性地(不下推)下推集合操作來減少Mysql執(zhí)行這些sql的效率低下。在第一代查詢引擎中,從葉子節(jié)點開始后序遍歷,記錄相同分片目標的節(jié)點,然后再次后序遍歷,直到遇上不滿足下推條件的節(jié)點,然后把它的子節(jié)點翻譯成SQL。
相似地,在第二代查詢引擎中也有類似邏輯,但是不像第一代引擎是有獨立的翻譯階段,而是與其他RBO規(guī)則一起在相同的優(yōu)化器里進行規(guī)則轉(zhuǎn)換,,同時轉(zhuǎn)換時候可以傳播排序信息,如果遇上能轉(zhuǎn)換為MegreSort的條件,就會馬上轉(zhuǎn)換,而無需在CBO階段中完成.若果MycatView階段在RBO階段已經(jīng)被提升到根節(jié)點,那也無需進行CBO了.當RBO完成的時候,根節(jié)點不是物理算子,會進行CRO進一步轉(zhuǎn)換成物理算子(第一代查詢引擎沒有這個階段),通過計算節(jié)點特征和行數(shù)等統(tǒng)計信息來選擇物理計劃。
MycatView的生成規(guī)則
設計目標是盡量生成簡單的SQL,同時讓后端數(shù)據(jù)庫(Mysql)執(zhí)行一定量的運算,總體來說,算子應該區(qū)分二階段
以MycatView為邊界,MycatView之上的算子為Mycat2執(zhí)行的算子,MycatView之下為MySQL要執(zhí)行的運算.MycatView之上的算子能否下推到MycatView之下,一般來說有兩個規(guī)則
RBO規(guī)則化轉(zhuǎn)換
基于兩個節(jié)點的下推判斷,?
指任意關(guān)系表達式
TableScan
TableScan=>MycatView(TableScan)
Filter
Filter(MycatView(Project(?)))≠>
Filter(MycatView(Set(?)))≠>
Filter(MycatView(Agg(?)))=>MycatView(Filter(Agg(?)):group by having語法
Filter(MycatView(Sort(?)))≠>
Filter(MycatView(Filter(?)))≠>MycatView(Filter(?)):需要MycatView之上合拼Filter
Filter(MycatView(Join(?)))=>MycatView(Filter(Join(?)))
Filter(MycatView(TableScan(?)))=>MycatView(Filter(TableScan(?)))
Project
Project(MycatView(Project(?)))=>MycatView(Project(Project(?)):盡量合拼Project
Project(MycatView(Set(?)))≠>
Project(MycatView(Agg(?)))=>MycatView(Project(Agg(?))
Project(MycatView(Sort(?)))≠>
Project(MycatView(Filter(?)))=>MycatView(Project(Filter(?)))
Project(MycatView(Join(?)))=>MycatView(Project(Join(?)))
Project(MycatView(TableScan(?)))=>MycatView(Project(TableScan(?)))
Join
Join(MycatView(Project(?)))≠>
Join(MycatView(Set(?)))≠>
Join(MycatView(Agg(?)))≠>
Join(MycatView(Sort(?)))≠>
Join(MycatView(Filter(?)))≠>
Join(MycatView(Join(?)))=>MycatView(Join(Join(?)))
Join(MycatView(TableScan(?)))=>MycatView(Join(TableScan(?)))
Agg
Agg(MycatView(Project(?)))=>MycatView(Agg(Project(?)))
Agg(MycatView(Set(?)))≠>
Agg(MycatView(Agg(?)))≠>
Agg(MycatView(Sort(?)))≠>
Agg(MycatView(Filter(?)))=>MycatView(Agg(Filter(?)))
Agg(MycatView(Join(?)))=>MycatView(Agg(Join(?)))
Agg(MycatView(TableScan(?)))=>MycatView(Agg(TableScan(?)))
Sort
Sort(MycatView(Project(?)))=>MycatView(Sort(Project(?)))
Sort(MycatView(Set(?)))≠>
Sort(MycatView(Agg(?)))=>MycatView(Sort(Agg(?)))
Sort(MycatView(Sort(?)))≠>
Sort(MycatView(Filter(?)))=>MycatView(Sort(Filter(?)))
Sort(MycatView(Join(?)))=>MycatView(Sort(Join(?)))
Sort(MycatView(TableScan(?)))=>MycatView(Sort(TableScan))
Set
Set(MycatView(Project(?)))≠>
Set(MycatView(Set(?)))≠>
Set(MycatView(Agg(?)))≠>
Set(MycatView(Sort(?)))≠>
Set(MycatView(Filter(?)))≠>
Set(MycatView(Join(?)))≠>
Set(MycatView(TableScan(?)))=>MycatView(Set(TableScan))
Correlate
Correlate(MycatView(Project(?)))≠>
Correlate(MycatView(Set(?)))≠>
Correlate(MycatView(Agg(?)))≠>
Correlate(MycatView(Sort(?)))≠>
Correlate(MycatView(Filter(?)))≠>
Correlate(MycatView(Join(?)))≠>
Correlate(MycatView(TableScan(?)))=>MycatView(Correlate(TableScan))
HBT執(zhí)行也是使用這套物理算子
MycatProject
MycatFilter
MycatNestedLoopJoin
MycatNestedLoopSemipJoin
SemiJoin版本的NestedLoopSemipJoin
MycatHashJoin
MycatSemiHashJoin
SemiJoin版本的MycatHashJoin
MycatBatchNestedLoopJoin(一般關(guān)閉,因為優(yōu)化器暫時沒有根據(jù)左側(cè)數(shù)據(jù)源得到行統(tǒng)計)
MycatSortMergeJoin
MycatMergeSemiJoin
SemiJoin版本的MycatHashJoin
MycatHashAgg
MycatSortAgg
MycatMemSort
MycatTopN
MycatMegreSort
MycatUnion
MycatMinus
MycatIntersect
MycatValues
MycatInsert
MycatUpdate
MycatTableModify
MycatView
MycatTransientSQLTableScan
建立臨時表
有一些要求輸入的數(shù)據(jù)源支持重復計算(迭代,rewind)的執(zhí)行器,Mycat2在不支持重復迭代的輸入源的執(zhí)行器會加上一個保存行數(shù)據(jù)的包裝器,這個包裝器會保存輸入的執(zhí)行器的數(shù)據(jù),這樣就可以得到支持重復迭代的執(zhí)行器。
一代與二代的配置不同
在第一代查詢引擎中,全局表配置是任意的,而沒有關(guān)于普通表的配置.這種設計的原因是配置一個單分片信息的全局表就具備普通表的功能.當分片表join全局表的時候,union的上推和分片sql的計算能把全局表與join的物理表join,然后合拼,并把相同分片節(jié)點的關(guān)系表達式變成sql.
而在第二代查詢引擎中,使用自定義的sql生成規(guī)則,對于全局表的語義,在join總是兩個子關(guān)系表達式式,多個join的時候總是以二叉樹的形態(tài)存在的時候,涉及全局表的join總是能下推的,如果全局表的schema與table名字不一樣,那么還需要計算對應的物理表是哪個.這樣略顯復雜,冗余,所以規(guī)定在第二代查詢引擎,全局表總是要存在所有分片,而且?guī)烀砻家恢?包括邏輯表.而對于普通表,如果采用MycatView的方法,即使是同一個分片的下推也是要計算對應的物理表。
全局表,普通表,分片表
在第二代查詢引擎中,要求全局表,普通表的物理庫名字,物理表名字分別與邏輯庫名字,邏輯表名字一致.
這樣的設計的好處是,mycat對于非用戶關(guān)心的sql,比如show語句,無需進行sql改寫表名,直接發(fā)到對應的物數(shù)據(jù)源上就可以了.更進一步的設計是指定一個物理數(shù)據(jù)源專門處理這些sql.而第一代查詢引擎涉及到了sql改寫,稍微復雜.
另外一個方面,全局表要求每個數(shù)據(jù)源上都有對應的物理表,而不像1代中,可以任意配置.這是為了與ER表下推全局表做簡化處理,如果簡化下推全局表的檢查過程.對于普通表,只需檢查sql的涉及的表信息,只有普通表的時候,直接把原sql發(fā)到數(shù)據(jù)源上即可,更一步的設計是固定一個數(shù)據(jù)源,對于普通表,或者沒有配置的表的sql,直接發(fā)到此節(jié)點.普通表與沒有配置的表的區(qū)別是前者顯式制定了他們會參與分片路由,而后者,一般來說,只是進行讀寫分離處理.對于分片表,分析出是sql中只有一個表,而且分析得出的分片算法。
對于分片表,物理庫與物理表的名字一般具有規(guī)律,有規(guī)律的名字容易與分片規(guī)則結(jié)合,生成物理表信息.無論在第一代查詢引擎與第二代查詢引擎中,都有明確指定配置分片信息設計傾向.主要原因是有些用戶分庫分表,有些是先分庫,此時他們的物理表,名字是相同的,有些用戶是先分表,他們的名字并不相同,還有一些用戶一開始就是分庫分表,然后選擇分庫來擴展性能.加上有些用戶的系統(tǒng)是已經(jīng)有分片的設計,后來再使用Mycat做分庫分表,有自己的表名規(guī)則.情況比較復雜,所以mycat在配置分片表,一般要求配置所有的存儲節(jié)點。
關(guān)于分片算法
關(guān)于DataNode
Mycat2總體設計上模糊了在1.6中dataNode的概念,并不明確.在1.6中,dataNode數(shù)據(jù)源和物理庫名為固定信息,而要求表名在路由中改寫(Mycat先去掉sql中的庫名.分庫不改寫表名,分表改寫表名),往大一點的方向來說,這個dataNode強調(diào)了節(jié)點這個概念,而固定物理庫名實際上是路由的改寫要求,.而在2.0中一個dataNode在配置中體現(xiàn)就是表分片(以后考慮配置中把dataNode更名,減少混亂).即其中一個分表,無論他是在一個數(shù)據(jù)源上還是在不同的物理庫.在Mycat2的早期sql生成機制中,如果只涉及一個數(shù)據(jù)源的sql,就使用union all合拼sql,也就是說,無論跨庫還是跨表,總能把查詢邏輯表的sql翻譯成查詢多個物理表的一條sql.但是由于mysql的執(zhí)行機制問題,性能并沒有顯著提高.所以Mycat2顯著的設計是默認對于涉及多個物理表的查詢,優(yōu)先并行拉取多個數(shù)據(jù)源的數(shù)據(jù),而使用union all合拼同一個數(shù)據(jù)源的結(jié)果集則是次要考慮。
更多建議: