深度解讀 Cascades 查詢最佳化器
資料庫中查詢最佳化器是資料庫的核心元件,其決定著 SQL 查詢的效能。Cascades 最佳化器是 Goetz 在 volcano optimizer generator 的基礎上最佳化之後誕生的一個搜尋框架。
本期技術貼將帶大家瞭解 Cascades 查詢最佳化器。首先介紹 SQL 查詢最佳化器,接著分析查詢最佳化基本原理,最後對 Cascades 查詢最佳化器進行重點介紹。
一、SQL 查詢最佳化器
使用者與資料庫互動時只需要輸入宣告式 SQL 語句,資料庫最佳化器則負責將使用者輸入的 SQL 語句進行各種規則最佳化,生成最優的執行計劃,並交由執行器執行。最佳化器對於 SQL 查詢具有十分重要的意義。
如圖 1 所示,SQL 語句經過語法和詞法解析生成抽象語法樹(AST),經過 基於規則的查詢最佳化(Rule-Based Optimizer)和 基於代價的查詢最佳化(Cost-Based Optimizer)生成可執行計劃。
圖 1
-
基於規則的最佳化演算法: 基於規則的最佳化方法的要點在於結構匹配和替換。應用規則的演算法一般需要先在關係代數結構上匹配一部分區域性的結構,再根據結構的特點進行變換乃至替換操作。
-
基於成本的最佳化演算法: 現階段主流的方法都是基於成本(Cost)估算的方法。給定某一關係代數代表的執行方案,對這一方案的執行成本進行估算,最終選擇估算成本最低的方案。儘管被稱為基於成本的方法,這類演算法仍然往往要結合規則進行方案的探索。基於成本的方法其實是透過不斷的應用規則進行變換得到新的執行方案,然後對比方案的成本優劣進行最終選擇。
二、查詢最佳化的基本原理
最佳化器一般由三個元件組成: 統計資訊收集、 開銷模型、 計劃列舉。
如圖 2 所示,開銷模型使用收集到的統計資訊以及構造的不同開銷公式,估計某個特定查詢計劃的成本,幫助最佳化器從眾多備選方案中找到開銷最低的計劃。
圖 2
SQL 語句查詢最佳化基於關係代數這一模型:
-
SQL 查詢可以轉化為關係代數;
-
關係代數可以進行區域性的等價變換,變換前後返回的結果不變但是執行成本不同;
-
透過尋找執行成本最低的關係代數表示,我們就可以將一個 SQL 查詢最佳化成更為高效的方案。
尋找執行成本最低的關係代數表示,可以分為 基於動態規劃的自底向上和 基於 Cascades/Volcano 的自頂向下兩個流派。
-
自底向上搜尋:從葉子節點開始計算最低成本,並利用已經計算好的子樹成本計算出母樹的成本,就可以得到最優方案;
-
自頂向下搜尋:先從關係運算元樹的頂層開始,以深度優先的方式來向下遍歷,遍歷過程中進行剪枝。
自底向上的最佳化器從零開始構建最優計劃,這類方法通常採用動態規劃策略進行最佳化,採用這類方法的最佳化器包括 IBMSystem R。自頂向下的最佳化策略的最佳化器包括基於 Volcano 和 Cascades 框架的最佳化器。
三、Cascades 查詢最佳化器
Cascades 查詢最佳化器採用自頂向下的搜尋策略,並在搜尋過程中利用 Memo 結構儲存搜尋的狀態。
Cascades 關鍵元件構成:
-
Expression:Expression 表示一個邏輯運算元或物理運算元。如 Scan、Join 運算元;
-
Group:表示等價 Expression 的集合,即同一個 Group 中的 Expression 在邏輯上等價。Expression 的每個子節點都是以一個 Group 表示的。一個邏輯運算元可能對應多個物理運算元,例如一個邏輯運算元 Join(a,b),它對應的物理運算元包括{HJ(a, b), HJ(b, a), MJ(a, b), MJ(b, a), NLJ(a, b), NLJ(b, a)}。我們將這些邏輯上等價的物理運算元稱為一個 Group(組)。注:HJ 表示 HashJoin 運算元,MJ 表示 MergeJoin 運算元,NLJ 表示 NestLoopJoin 運算元;
-
Memo:由於 Cascades 框架採用自頂向下的方式進行列舉,因此,列舉過程中可能產生大量的重複計劃。為了防止出現重複列舉,Cascades 框架採用 Memo 資料結構。Memo 採用一個類似樹狀(實際是一個圖狀)的資料結構,它的每個節點對應一個組,每個組的成員透過連結串列組織起來;
-
Transformation Rule:是作用於 Expression 和 Group 上的等價變化規則,用來擴大最佳化器搜尋空間。
Cascades 首先將整個 Operator Tree 按節點複製到一個 Memo 的資料結構中,Memo 由一系列的 Group 構成,每個運算元放在一個 Group,對於有子節點的運算元來說,將原本對運算元的直接引用,變成對 Group 的引用。
圖 3
如圖 3 所示,生成該語法樹的 Memo 初始結構。Memo 結構中一個圓角框代表一個運算元,圓角框右下角是對其 Children’s Groups 的引用,左下角是識別符號。生成初始的 Memo 結構後,可以採用 transform rule 進行邏輯等價轉換,規則如下:
-
對於一個邏輯運算元,其所有基於關係代數的等價表示式儲存在同一個 Group 內,例如 join(A,B) -> join(B,A);
-
在一個 Group 內,對於一個邏輯運算元,會生成一個或多個物理運算元,例如 join -> hash join,merge join,NestLoop join;
-
一個 Group 內,一個運算元,其輸入(也可以理解為subplan)可以來自多個 Group 的表示式。
在圖 4 中,描述了一個部分擴充套件的 Memo 結構,與圖 1 中的初始 Memo 相比,在同一個 Group 內,增加了等價的邏輯運算元,以及對應的物理運算元。
圖 4
在探索的過程中,最佳化器就會透過開銷模型 Coster 藉助統計資訊來計運算元步驟的開銷,遍歷完每個 Memo Group之後,歸總得到每個完整計劃的總開銷,最終選擇 Memo 中開銷最低的計劃。
圖 5
圖 5 中有三個 Group,分別對應三個邏輯運算元:Join(a, b), GET(a) 和 GET(b)。Group 1(Group 2)中包含了所有對應 GET(a) (GET(b))的物理運算元,我們可以估算每個物理運算元的代價,選取其中最優的運算元保留下來。
為了防止列舉過程出現重複列舉某個表示式,Memo 結構體中還包含一個雜湊表(exprHT),它以表示式為雜湊表的鍵,用來快速查詢某個表示式是否已經存在於 Memo 結構體中。
Cascades 採用自頂向下的方式來進行最佳化,以計劃樹的根節點為輸入,遞迴地最佳化每個節點或表示式組。如圖所示,整個最佳化過程從 Group 0 開始,實際上要先遞迴地完成兩個子節點(Group 1 和 Group 2)的最佳化。
因此,實際的最佳化完成次序是 Group 1 -> Group2 -> Group 0。在最佳化每個 Group 時,依次最佳化每個組員;在最佳化每個組員時,依次遞迴地最佳化每個子節點。依次估算當前組裡每個表示式 e 的代價 cost(e),選擇最低得代價結果儲存在 bestHT 中。最佳化結束時,查詢 Join(a,b)對應的 Memo 結構體,獲取最低的執行計劃。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027415/viewspace-2999694/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深度解讀GaussDB(for MySQL)與MySQL的COUNT查詢並行最佳化策略MySql並行
- 查詢最佳化器的引數設定
- PostgreSQL 原始碼解讀(20)- 查詢語句#5(查詢樹Query詳解)SQL原始碼
- vertica查詢最佳化
- MySQL查詢最佳化MySql
- 深度解讀《深度探索C++物件模型》之返回值最佳化C++物件模型
- PostgreSQL 原始碼解讀(24)- 查詢語句#9(查詢重寫)SQL原始碼
- PostgreSQL 原始碼解讀(29)- 查詢語句#14(查詢優化-上拉子查詢)SQL原始碼優化
- StoneDB 子查詢最佳化
- 最佳化星型查詢
- oracle的查詢最佳化Oracle
- MySQL查詢效能最佳化MySql
- [Mysql]慢查詢最佳化MySql
- Oracle 最佳化器與sql查詢執行順序OracleSQL
- PostgreSQL 原始碼解讀(25)- 查詢語句#10(查詢優化概覽)SQL原始碼優化
- PostgreSQL 原始碼解讀(17)- 查詢語句#2(查詢優化基礎)SQL原始碼優化
- ByteHouse 查詢最佳化器的設計與實現
- 慢查詢最佳化及分析
- 【Mysql】MySQL查詢最佳化-explainMySqlAI
- 遇到慢查詢怎麼辦?一文解讀MySQL 8.0查詢分析工具MySql
- Laravel 原始碼閱讀指南 -- Database 查詢構建器Laravel原始碼Database
- PostgreSQL 原始碼解讀(36)- 查詢語句#21(查詢優化-消除外連線)SQL原始碼優化
- PostgreSQL 原始碼解讀(37)- 查詢語句#22(查詢優化-grouping_plan...SQL原始碼優化
- MySQL-10.索引最佳化與查詢最佳化MySql索引
- 查詢效能較 Trino/Presto 3-10 倍提升!Apache Doris 極速資料湖分析深度解讀RESTApache
- MySQL 如何最佳化大分頁查詢?MySql
- 【最佳化】模糊查詢索引問題索引
- 資料庫之查詢最佳化資料庫
- Microsoft SQL Server查詢最佳化方法ROSSQLServer
- 【GaussDB(for MySQL)】 Big IN查詢最佳化MySql
- 資料統計查詢最佳化
- PostgreSQL 原始碼解讀(19)- 查詢語句#4(ParseTree詳解)SQL原始碼
- 【原始碼解讀(一)】EFCORE原始碼解讀之建立DBContext查詢攔截原始碼Context
- 騰龍【大資料clickhouse】clickhouse 常用查詢最佳化策略詳解大資料
- PostgreSQL 原始碼解讀(26)- 查詢語句#11(查詢優化-上拉子連結#1)SQL原始碼優化
- PostgreSQL 原始碼解讀(27)- 查詢語句#12(查詢優化-上拉子連結#2)SQL原始碼優化
- PostgreSQL 原始碼解讀(28)- 查詢語句#13(查詢優化-上拉子連結#3)SQL原始碼優化
- PostgreSQL 原始碼解讀(33)- 查詢語句#18(查詢優化-表示式預處理#3)SQL原始碼優化