Mycat2 執(zhí)行計劃管理

2021-09-09 15:34 更新

Mycat2的執(zhí)行計劃管理主要作用是管理執(zhí)行計劃,加快SQL到執(zhí)行計劃的轉(zhuǎn)換,并且提供一個方式可以從持久層讀取自定義的執(zhí)行計劃.它與緩存結(jié)果集不同,它更接近傳統(tǒng)分庫分表的緩存路由.Mycat2引入這個功能的初衷是Calcite在分析復(fù)雜SQL的耗時比較大.整體設(shè)計上參考了Oracle,Polardb-X的文檔.該功能在v1.18開始提供.

LOGIC SQL

邏輯SQL,其中邏輯一詞對應(yīng)的邏輯庫,邏輯表中的邏輯.它描述對邏輯庫邏輯表的操作.它在Mycat2里也叫DrdsSQL,它包含了參數(shù)化SQL,參照綁定值,它們的類型,以及該SQL的字段別名.一個邏輯SQL的SQL模板具有多個基線,因為約束不同.

BASELINE

SQL運行計劃基線,簡稱基線.在Mycat2里,基線包含執(zhí)行計劃的'類型',邏輯SQL通過'約束'來校驗該BASELINE是否適用.一個基線可以對應(yīng)多個執(zhí)行計劃,它們的關(guān)系類似接口與實現(xiàn)的關(guān)系.而其中不同執(zhí)行計劃可能對不同的參數(shù)值具有不同的執(zhí)行代價.它也可以通過FIX命令強制綁定一個基線對應(yīng)一個執(zhí)行計劃,此時是一個基線對應(yīng)一個執(zhí)行計劃.基線在執(zhí)行計劃管理中最重要的作用是提供穩(wěn)定的執(zhí)行計劃,這是緩存執(zhí)行計劃后自然得到的效果.如果緩存有一定的失效,更新周期,則可以通過一定條件觸發(fā)更新,結(jié)合新的統(tǒng)計信息,可以發(fā)現(xiàn)更優(yōu)的執(zhí)行計劃.

PLAN

一個執(zhí)行計劃對應(yīng)一種執(zhí)行器,它包含計算代價的函數(shù),也能生成執(zhí)行器實例,它還包含了生成它的'原因',比如通過hint影響導(dǎo)致的生成了該計劃(baseline中的SQL模板是不帶hint的).

EXECUTOR

執(zhí)行器是執(zhí)行計劃生成的.它需要使用邏輯SQL的信息(參數(shù)值)才可以執(zhí)行并輸出結(jié)果集.同時,它在執(zhí)行的時候可以統(tǒng)計執(zhí)行的運行時信息,并反饋到統(tǒng)計器.因為參數(shù)化之后,selectItem表達式中可能包含帶有?的情況,所以字段名與參數(shù)值相關(guān).結(jié)果集輸出的字段信息需要使用邏輯SQL的別名信息.最后,它是與參數(shù)值類型強相關(guān)的,因為表達式計算包含對應(yīng)的類型轉(zhuǎn)換.

選擇緩存的執(zhí)行計劃

其中挑選對于當前參數(shù)值具有最小執(zhí)行成本的過程,實際上是SQL編譯優(yōu)化中代價分析過程的精簡版,因為它沒有使用復(fù)雜的框架進行分析也沒有生成執(zhí)行計劃的過程,而是僅僅對已有的執(zhí)行計劃代價計算函數(shù)賦值,計算得到代價,從中選擇最小的來執(zhí)行.

服務(wù)器預(yù)處理語句中的延后編譯

對于有些SQL中帶有?參數(shù)的情況,它們的類型在Mycat2不能推導(dǎo).Mycat2對于這種情況的處理是延后編譯.在真正收到實際參數(shù)的時候,在把SQL模板與實際參數(shù)結(jié)合生成完整的,不帶有?的語法樹(AST),然后再進行參數(shù)化處理,生成新的SQL模板,參數(shù)和SQL模板約束.盡管MySQL在8.0.22有了相關(guān)的類型推導(dǎo)規(guī)則,它可以進一步,提早編譯即在預(yù)處理prepare階段就編譯,但是Mycat2暫時不實現(xiàn)它.

BASELINE和PLAN在哪里持久化

他們存儲在原型庫(prototype),在mycat庫下的spm前綴的表里,一般是spm_baselinespm_plan這兩個表.原型庫可能被多個Mycat2同時操作訪問,涉及修改數(shù)據(jù)的情況,mycat會開啟串行事務(wù)進行操作.baselineplanid也是全局唯一的,它們的生成方法與mycat的workid相關(guān).

持久化是否必須的

不是的,但是對于Mycat2來說,執(zhí)行計劃緩存是必須的.因為Mycat2的執(zhí)行器使用了針對SQL模板生成對應(yīng)的關(guān)系表達式,進一步編譯成執(zhí)行器.如果對于每一條SQL都進行該過程,則性能不佳.如果僅僅進行在Mycat2運行的時候緩存生成的,而Mycat2關(guān)閉.重啟后,執(zhí)行計劃緩存就丟失了.用戶會在第一次使用SQL訪問的時候,明顯感覺Mycat2很慢.對于這個情況,可以減少一些優(yōu)化過程,減少編譯時間,但是會導(dǎo)致生成的執(zhí)行計劃不佳的情況.所以Mycat2添加了對執(zhí)行計劃持久化的功能.

Accept狀態(tài)

Mycat2暫時沒有實現(xiàn)自動演化,所以獲得的執(zhí)行計劃都是Accept=true的狀態(tài).在實現(xiàn)自動演化的執(zhí)行計劃管理中,如果觸發(fā)了執(zhí)行計劃演化,可能會得到新的執(zhí)行計劃,它可能在一定條件下,理論上比現(xiàn)有的緩存的執(zhí)行計劃更具有性能優(yōu)勢,但是此時該執(zhí)行計劃是沒有被驗證的(Accept=false),它還不能設(shè)置為Accept=true.它需要經(jīng)過一定的驗證過程(比如流量灰度),證明它比現(xiàn)有的執(zhí)行計劃確實在一定條件更加才會被設(shè)置為Accept=true.

暫時的問題與局限

用戶維護持久化的執(zhí)行計劃的一致性

一方面,因為Mycat2保留了中間件的文件文件配置(ZK也是如此),允許了用戶脫離Mycat2的感知直接操作配置文件,所以如果手動更改了表的配置,導(dǎo)致持久化的執(zhí)行計劃與表的信息不一致,則會導(dǎo)致數(shù)據(jù)查詢錯誤.對于這種情況,需要用戶自行刪除持久化的執(zhí)行計劃..因為自動型hash的表允許使用SQL來修改表,所以它支持自動刪除表相關(guān)的執(zhí)行計劃(一般的數(shù)據(jù)庫是在更改表配置后自動刪除緩存的執(zhí)行計劃的).

不會自動持久化執(zhí)行計劃

另一方面,Mycat2不會自動進行把內(nèi)存中的執(zhí)行計劃持久化,這與其他數(shù)據(jù)庫不同,它們在遇上復(fù)雜SQL的時候會自動持久化.而Mycat2提供了一個把內(nèi)存中所有基線及其執(zhí)行計劃持久化的命令.用于準備上生產(chǎn)或者測試的時候保存執(zhí)行計劃.Mycat2在啟動時候會自動加載(load)原型庫中存在的執(zhí)行計劃.如果遇上不一致的問題,把這涉及的表數(shù)據(jù)清空即可.

不會自動進行執(zhí)行計劃演化以及淘汰

對于已經(jīng)緩存的執(zhí)行計劃,Mycat2就會使用已有的(一個)執(zhí)行計劃,不會自動演化新的執(zhí)行計劃(統(tǒng)計信息變化,表配置變化).

手動演化以及淘汰

Mycat2提供了管理執(zhí)行計劃的命令,供用戶對執(zhí)行計劃進行操作.值得注意的是,它是涉及兩個存儲空間的,Mycat2內(nèi)存緩存以及原型庫的持久化存儲,對于其中一個Mycat2實例進行的內(nèi)存操作不會發(fā)生在另一個Mycat2實例上.

首先,Mycat2在啟動時候一定會加載原型庫的存在的執(zhí)行計劃.加載完畢才啟動成功.然后,Mycat2就處于運行狀態(tài).此后Mycat2將不會自動對原型庫中的涉及持久化的執(zhí)行計劃的表進行操作.而是僅僅在Mycat2內(nèi)存中的緩存進行添加操作(如果遇上沒有執(zhí)行計劃的SQL).

如果用戶使用執(zhí)行計劃管理命令才會涉及到對原型庫的操作.

查詢命令

LIST 顯示所有執(zhí)行計劃,包含未持久化的,已經(jīng)持久化的執(zhí)行計劃. 但是不會把持久化的基線/執(zhí)行計劃替換內(nèi)存中的基線/執(zhí)行計劃

BASELINE LIST 

管理命令(它們的參數(shù)就是plan_id或者baseline_id)

LOAD 把持久化的基線及其執(zhí)行計劃加載(替換)到內(nèi)存

BASELINE LOAD xxxxx

BASELINE LOAD_ALL_BASELINES

該命令會在Mycat2啟動時候自動執(zhí)行

把持久化中的基線加載到內(nèi)存

BASELINE LOAD_ALL_BASELINES

BASELINE PERSIST_ALL_BASELINES

把內(nèi)存中的所有基線及其執(zhí)行計劃持久化

BASELINE PERSIST_ALL_BASELINES

LOAD_PLAN 把持久化的執(zhí)行計劃加載(替換)到內(nèi)存

BASELINE LOAD_PLAN xxxxx

PERSIST 把內(nèi)存中的基線持久化

BASELINE PERSIST xxxxx

PERSIST_PLAN 把內(nèi)存中的執(zhí)行計劃持久化

BASELINE PERSIST_PLAN xxxxx

CLEAR 清理內(nèi)存中的基線,但是不會清理持久化的基線

BASELINE CLEAR xxxxx

CLEAR_PLAN 清理內(nèi)存中的執(zhí)行計劃,但是不會清理持久化的執(zhí)行計劃

BASELINE CLEAR_PLAN xxxxx

DELETE 刪除持久化的基線,但是不會清理內(nèi)存中的執(zhí)行計劃

BASELINE DELETE xxxxx

DELETE_PLAN 刪除持久化的執(zhí)行計劃,但是不會清理內(nèi)存中的執(zhí)行計劃

BASELINE DELETE_PLAN xxxxx

ADD/FIX

根據(jù)SQL(帶hint)添加執(zhí)行計劃,而FIX命令則是把執(zhí)行計劃與基線綁定.該命令不會自動持久化基線與執(zhí)行計劃.

在創(chuàng)建執(zhí)行計劃的時候遇上沒有基線的情況會自動創(chuàng)建對應(yīng)的基線.如果add/fix命令生成的執(zhí)行計劃與現(xiàn)有緩存的執(zhí)行計劃相同則使用現(xiàn)有的執(zhí)行計劃.

BASELINE ADD /*+ mycat:xxx*/ select 1
BASELINE FIX /*+ mycat:xxx*/ select 1

UNFIX

取消基線與執(zhí)行計劃綁定

參數(shù)是基線id


BASELINE UNFIX xxxx
``
### 基于腳本的自動演化
  整體來說,手動演化和淘汰可以結(jié)合用戶編寫的SQL腳本(根據(jù)一定的情況進行觸發(fā))進行調(diào)用實現(xiàn)自動演化的效果.它與數(shù)據(jù)庫自動演化的方式的區(qū)別是數(shù)據(jù)庫掌握更多的觸發(fā)條件,比如執(zhí)行計劃占用的內(nèi)存大小以及整個執(zhí)行計劃管理器的內(nèi)存空間大小.


### 序列化的執(zhí)行計劃
  Mycat2的執(zhí)行計劃支持json格式序列化并反序列化成執(zhí)行計劃.所以可以修改保存在數(shù)據(jù)庫中執(zhí)行計劃來實現(xiàn)修改執(zhí)行器的行為.
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號