CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

OceanBase開源社群發表於2022-03-23

高手雲集,群英薈萃。

2022年3月19日 CSDN 資料庫沙龍上,眾多技術專家彙集在 資料庫線上 Meetup 直播現場,來自 OceanBase 技術專家田逸飛(花名:義博)為大家精彩講述了 OceanBase SQL 的一生。


本次分享從一條 SQL 被資料庫接收開始,一直到執行結束,講述了資料庫中的整體執行流程,以及瞭解 OceanBase 如何讓同一類 SQL 共享執行計劃,通過這條SQL的一生,幫助大家更好的瞭解和掌握 SQL 執行流程和計劃快取兩大模組。

一、SQL 執行流程


1.SQL 執行流程介紹

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生


從圖中我們可以看到,當使用者從 SQL 傳送到 OBServer 後,會先由 OBServer 對其進行快速引數化,引數化後的 SQL 進入 Plan Cache 嘗試命中計劃快取 。當找到一個可以使用的計劃,則直接將計劃交由 SQL 的執行引擎去執行,並將執行完成後的結果返回給使用者;如果沒有找到可以使用的計劃,則會重新為此 SQL 生成計劃,完整地執行 SQL 的Parser、Resolver、Transformer、Optimizer、Code Generator 解析流程,然後生成一個可用的物理執行計劃,並交由執行引擎執行,同時此計劃會被加入到計劃快取,以便後續的 SQL 重新使用,詳見下圖。


2.查詢改寫

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

如下圖所示,流程中的 Parser 主要負責語法詞法的解析,它會將使用者輸入的 SQL 基於 lax 和 yacc 生成一個 Parse Node Tree,如下圖右側所示,它將使用者的 SQL 拆成了一個樹狀結構,同時做了一些語法解析。


3.語義分析

Resolver 負責對 Parse Node Tree 做語義的分析,主要包括語句的解析、中綴表示式的生成、表示式的型別推導等,並最終將其轉化成 OceanBase 在程式碼中更易於操作的資料結構


4.查詢改寫

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

Transformer 會在保證 SQL 執行結果相同並且正確的情況下對 SQL 做等價變換。目前在 OceanBase 中存在兩類改寫。

  • 基於規則的改寫,這一類改寫總是會把 SQL 向好的方向改寫,比如 join 連線消除改寫
  • 基於代價的改寫,這一類改寫發生後 SQL 的效能可能變得更好或者更差。對於這一類的改寫,會分別計算髮生改寫 SQL 和不發生改寫的代價。在比較之後,對於那些發生改寫後代價低時 OceanBase 選擇改寫;而發生改寫 SQL 後代價更高的情況,則不去選擇改寫。

 


5. 查詢優化

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

在 Transformer 做完等價改寫之後,將改寫後的 SQL移交至 Optimizer ,也就是查詢優化模組中,由 Optimizer 繼續生成邏輯計劃。Optimizer 會對使用者的 SQL 生成一組可選的邏輯計劃,從這些所有的邏輯計劃中選出一個優化器所認為的最優計劃,詳見上圖。


 

在這個過程中,Optimizer 會結合代價模型和統計資訊,做基表路徑、連線順序、連線演算法的選擇以及分散式計劃的生成等。並且在做出這些選擇的過程中, Optimizer 還會有一些基於規則的剪枝和 Skyline 剪枝的優化,通過這些剪枝規則減少優化過程中路徑的數量,降低優化的複雜度,從而提升優化速度。

 

 


6 .程式碼生成

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

在 Optimizer 模組完成後,便得到了 SQL 的邏輯計劃,而這個邏輯計劃被移交 Code Generator 做程式碼生成,因為此時的邏輯執行計劃不能被直接執行。所以 Code Generator 需要將邏輯的執行計劃翻譯,生成執行引擎可識別、可執行的物理執行計劃。也就是說,Code Generator在這裡所做的事情其實就是單純的對邏輯執行計劃做一個轉換,包括將邏輯執行計劃中的邏輯運算元轉換成物理運算元。

經過 Code Generator 這個步驟 ,我們得到可以實際執行的物理執行計劃,而這個物理執行計劃也會被交由 Executor ,也就是我們的執行引擎去執行。


7. 執行引擎

在 OceanBase 中的執行引擎使用的是火山模型。火山模型在資料庫中非常常見,是經典的資料執行模型。除此之外,OceanBase 的執行引擎還提供了並行執行框架,比如說當 CPU 資源容量足夠多時 ,使用者可通過開啟並行機制來提高 SQL 的執行效能。


二、計劃快取

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

在將計劃快取之前,先介紹一下計劃快取的兩種匹配模式:

Foece 模式和 Exact 模式


1.Force 模式

這是 OceanBase 預設的匹配模式。 Force 模式下,首先會對 SQL 裡面的常量進行引數化,再對引數化後的計劃進行匹配。什麼是引數化呢?如上圖右側 SQL 語句, select c1,c2 from t1 where c1=1,這裡的1 是一個常量。引數化就是將常量替換成一個萬用字元“?”。所以引數化之後,這條 SQL 就變成了 select c1,c2 from t1 where c1=?。

引數化之後,文字與此條 SQL 一樣的 SQL 都可以共享一個計劃。比如這裡 where c1=1、c1=2、c1=3的語句都可以共用同一個執行計劃。但它的不足之處在於 SQL 命中的計劃可能並不是一個最優的執行計劃。

依然以上述 SQL 為例,假設對於 t1 中,c1=1 的值佔了1%,c1=0 的值佔了99%,即表裡的c1 只有 1 和 0 兩個取值。

假設一開始計劃快取是空,先來了一個 c1=1 的 SQL,就會用這條 SQL 去生成計劃。如果c1=1 的過濾性非常好的,則會選一個走 c1 索引的計劃,相當於在 c1 的索引上做一次掃描,然後做索引回表,並將計劃快取到計劃快取中。但是如果之後來了一個 c1=0 的 SQL,那麼它就會命中剛剛生成的計劃走索引掃描。但是對於 c1=0的條件,索引其實不是最優的,

因為它不能過濾掉大量資料。索引掃描完成後它還有 99% 的資料要做索引回表。在這種場景下,索引往往不如基表掃描快。


2.Exact 模式

Exact模式下,做計劃匹配的時候不會做引數化,而是直接用原始的 SQL 去做匹配,匹配的時候要求 SQL 的文字完全相同。比如大小寫、空格的數量以及引數都要相同才能共享計劃。

它的優點在於不同的引數都能選到自己最優的計劃。不足之處也非常明顯——計劃的命中率非常低。比如通過主鍵去查詢表裡某一行具體的資料,主鍵在表中的每一個值都是不同的,也就意味著它們都無法共享計劃,每一個主鍵值都要重新生成一次計劃,這就導致計劃的命中率非常低。而且大量的計劃會導致計劃快取的記憶體會大幅膨脹。

 

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

上圖展示了一些計劃共享的例子。

第一組 SQL 引數化之後都會變成 select c1,c2 from t1 where c1=? and c2 =?。它們引數化後的 SQL 文字是相同的,因此可以共享計劃。

 

第二組 SQL 引數化之後變成了select c1,c2 from t1 where c1=? order by ?。

但實際上它們的語義是不一樣的,第一條 order by 1,意味著要對 select 裡的第一列做排序,而第二條意味著要對 s

elect 裡的第二列做排序。如果它們共享計劃,兩個結果一定會出現問題。


為了防止這樣錯誤的共享計劃,OceanBase引入了額外的約束機制。比如對於第一條 SQL ,要求 order by=1 的時候才能使用它生成的計劃,同理對於第二條 SQL 會要求 order by=2 的時候才能使用它生成的計劃。


第三組 SQL 引數化之後會變成 select c1,c2 from t1 where c1=? and ? = ?。而它在 OceanBase 中也是無法共享計劃的。因為1 = 1是一個恆 true的條件,而 1 = 2 是一個恆 false 的條件。對於這種恆 true、恆 false 的條件,OceanBase 在改寫優化的過程中會對其做一些特殊處理,簡化這些計劃的生成過程和生成的計劃。一旦不同的恆 true、恆 false 條件共享了計劃,也會導致一些結果錯誤。

 

對於上述場景, OceanBase 也會抽取出約束。比如對於第一條 SQL,它會要求第二個引數等於第三個引數的計算結果是 true 的時候才能共享這條 SQL 產生生成的計劃;對於第二條 SQL,它會要求第二個引數等於第三個引數的計算結果是 false 的時候才能共享第二條 SQL 產生的計劃。


第四組 SQL 的問題在於 select 的大小寫不同,因此也不能共享計劃。

 


3.SQL 執行計劃獲取過程

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

這裡的圖片內容跟第一部分幾乎完全相同。對於一個 SQL 請求,OceanBase 會對這條 SQL 做一次快速引數化,並用引數化後的 SQL 到計劃快取中匹配執行計劃。這裡存在能匹配到計劃和匹配不到計劃兩種情況。如果匹配到就去執行;而匹配不到則將走完一個完整 SQL 執行流程,先在 Parser 中做詞法語法解析。具體流程是: SQL 先通過 Parser 做語法詞法解析,然後做一次普通引數化,最後再做剩下的 Resolver、Transformer、Optimizer 等一系列過程。

 


4.快速引數化和普通引數化區別

快速引數化

快速引數化的功能:通過語法分析快速將 SQL 中常量值替換為萬用字元的問號。

快速引數化只依賴詞法分析即可直接基於 SQL 文字做引數化,對 Parser 的依賴小,引數化效率高。

在引數化的過程 中 OceanBase 會記錄當前 SQL 的引數資訊,用於計劃匹配時檢查是否滿足約束。

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

 

普通引數化

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

普通引數化是基於 Parser 的結果進行引數化的過程。在 Parser 之後我們已經得到了 SQL 完整的語法詞法樹,也就獲得了 SQL 的語義資訊。在這個基礎上我們做引數化可以進行一些額外的操作,例如約束的抽取。當我們對上圖中的語法詞法樹進行引數化時,會發現 order by 後是一個常量,這個時候我們就會抽取約束,要求 order by 後的引數必須為1時才能共享這條 SQL 生成的計劃。


5.計劃更新

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生

生成的物理執行計劃並非一成不變,在某個時間點生成的計劃只能表示,

一條 SQL 在特定時間點最優的計劃。但在資料庫中,表的結構、表中資料量、表中資料值的分佈都可能會發生變化,在各種因素的不斷變化中,不能保證在某一個時間點生成的計劃永遠是最優的。所以計劃一定需要在合適的時機更新,從而保證這個計劃相對來說是最優計劃。


OceanBase 計劃更新場景

  • 執行計劃依賴物件的 Scheme 發生變化

比如資料表T1,在T1上新建一個索引,建立索引的動作會導致T1表 schema 的版本號被推高,而當檢測到schema 版本號推高時,計劃快取中所有涉及到T1表的計劃全部失效。如果此時一條新的 SQL 完全依賴這個資料表T1 ,就會重新生成計劃。因此這時新計劃極可能用新建索引做出更好的優化。

  • 統計資訊發生改變

當統計資訊發生變化時,可以利用更新的統計資訊重新生成計劃。比如當列的直方圖、NDV值、最大最小值更新時,優化器可以使用這些新的統計資訊去生成更好的計劃。

  • 執行反饋需要更新計劃

通過執行反饋發現當前的執行計劃,相比於它生成計劃時的效能更差。這時即可將此計劃完全淘汰,重新生成計劃。

 

以上就是關於在 OceanBase 中 SQL 執行流程和計劃快取的所有內容。非常期待和歡迎大家到 OceanBase 開源社群參與討論、交流和互動,請掃描以下二維碼,快速與我們聯絡。

CSDN 資料庫Meetup|OceanBase 技術專家講述 SQL 的一生


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70005215/viewspace-2883544/,如需轉載,請註明出處,否則將追究法律責任。

相關文章