mysql cbo优化器_查询优化器介绍 - PolarDB-X 云原生分布式数据库 - 阿里云
PolarDB-X接收到一條SQL后的執行過程大致如下:
語法解析器(Parser)將SQL文本解析成抽象語法樹(AST)。
語法樹被轉化成基于關系代數的邏輯計劃。
優化器(Optimizer)對邏輯計劃進行優化得到物理計劃。
執行器(Executor)執行該計劃,得到查詢結果并返回給用戶。
本章將會介紹查詢優化器的基本原理,包含如下幾個方面:
關系代數算子。
查詢改寫(RBO階段)。
查詢計劃枚舉(CBO階段)。
關系代數算子
一條SQL查詢在數據庫系統中通常被表示為一棵關系代數算子組成的樹,有如下場景的算子:
Project:用于描述SQL中的SELECT列,包括函數計算。
FIlter:用于描述SQL中的WHERE條件。
JOIN:用于描述SQL中的JOIN,其對應的物理算子有HashJoin、 BKAJoin、Nested-Loop Join、SortMergeJoin。
Agg:用于描述SQL中的Group By及聚合函數,其對應的物理算子有HashAgg、SortAgg。
Sort:用于描述SQL中的Order By及Limit,其對應的物理算子有TopN、MemSort。
LogicalView:用于描述PolarDB-X下發至RDS MySQL或PolarDB MySQL的SQL,其內部可能包含一個或多個邏輯算子。
Gather:代表從多個數據流匯集數據的操作,通常出現在LogicalView之上(若開啟并行執行,則并行優化步驟會將其上拉)。
例如,對于如下查詢SQL(修改自TPC-H Query 3):
SELECT l_orderkey,sum(l_extendedprice*(1-l_discount))AS revenue
FROM CUSTOMER,ORDERS,LINEITEM
WHERE c_mktsegment='AUTOMOBILE'
andc_custkey=o_custkey
andl_orderkey=o_orderkey
ando_orderdate
andl_shipdate>'1995-03-13'
GROUP BY l_orderkey;
通過如下EXPLAIN命令看到PolarDB-X的執行計劃:
HashAgg(group="l_orderkey",revenue="SUM(*)")
HashJoin(condition="o_custkey = c_custkey",type="inner")
Gather(concurrent=true)
LogicalView(tables="ORDERS_[0-7],LINEITEM_[0-7]",shardCount=8,sql="SELECT `ORDERS`.`o_custkey`, `LINEITEM`.`l_orderkey`, (`LINEITEM`.`l_extendedprice` * (? - `LINEITEM`.`l_discount`)) AS `x` FROM `ORDERS` AS `ORDERS` INNER JOIN `LINEITEM` AS `LINEITEM` ON (((`ORDERS`.`o_orderkey` = `LINEITEM`.`l_orderkey`) AND (`ORDERS`.`o_orderdate` < ?)) AND (`LINEITEM`.`l_shipdate` > ?))")
Gather(concurrent=true)
LogicalView(tables="CUSTOMER_[0-7]",shardCount=8,sql="SELECT `c_custkey` FROM `CUSTOMER` AS `CUSTOMER` WHERE (`c_mktsegment` = ?)")
用樹狀圖表示如下:
左邊的LogicalView實際包含了ORDERS和LINEITEM兩張表的JOIN。EXPLAIN結果中LogicalView的SQL屬性也體現了這一點。
查詢改寫(RBO)
查詢改寫(SQL Rewrite)階段輸入為邏輯執行計劃,輸出為邏輯執行計劃。這一步主要應用一些啟發式規則,是基于規則的優化器(Rule-Based Optimizer,簡稱RBO),所以也常被稱為RBO階段。
查詢改寫這一步的主要有如下功能:
子查詢去關聯化(Subquery Unnesting)
子查詢去關聯化是將含有關聯項的子查詢(關聯子查詢)表示為SemiJoin或類似的算子,便于后續的各種優化處理,例如下推到MySQL或在PolarDB-X層選擇某種算法執行。
在如下例子中IN子查詢轉化為SemiJoin算子,并最終轉化成SemiHashJoin物理算子由PolarDB-X進行執行:
>explainselectidfromt1whereidin(selectidfromt2wheret2.name='hello');
SemiHashJoin(condition="id = id",type="semi")
Gather(concurrent=true)
LogicalView(tables="t1",shardCount=2,sql="SELECT `id` FROM `t1` AS `t1`")
Gather(concurrent=true)
LogicalView(tables="t2_[0-3]",shardCount=4,sql="SELECT `id` FROM `t2` AS `t2` WHERE (`name` = ?)")
算子下推
算子下推是非常關鍵的一步,PolarDB-X內置了如下算子的下推優化規則:謂詞下推或列裁剪:將Filter及Project算子下推至MySQL執行,過濾掉不需要的行和列。
JOIN Clustering:將JOIN按照拆分方式及拆分鍵相等進行重排和聚簇,方便下一步的JOIN下。
JOIN下推:對于符合條件的JOIN,將其下推至MySQL執行。
Agg下推:將聚合(Agg)拆分為FinalAgg和LocalAgg兩個階段,并將LocalAgg下推至MySQL。
Sort下推:將排序(Sort)拆分為MergeSort和LocalSort兩個階段,并將LocalSort下推至MySQL。
更多關于查詢下推的信息,請參見查詢改寫與下推。
查詢計劃枚舉(CBO)
經過查詢改寫階段的邏輯執行計劃會被輸入到查詢計劃枚舉(Plan Enumerator),輸出一個最終的物理執行計劃。
查詢計劃枚舉在多個可行的查詢計劃中,根據預先定義的代價模型,選擇出代價最低的一個。與查詢改寫階段不同,在查詢計劃枚舉中,規則可能產生更好的執行計劃,也可能產生更差的執行計劃,我們會根據前后的代價相比較來選擇出較優的那個,因此這也被稱為基于代價的優化(Cost-based Optimizer,簡稱CBO)。
其核心組件有以下幾個部分:
統計信息(Statistics)
基數估計(Cardinality Estimation)
轉化規則(Transform Rules)
代價模型(Cost Model)
計劃空間搜索引擎(Plan Space Search Engine)
邏輯上,CBO的過程包括如下幾個步驟:
搜索引擎利用轉化規則,對輸入的邏輯執行計劃進行變換,構造出物理執行計劃的搜索空間。
之后,利用代價模型對搜索空間中的每一個執行計劃進行代價估計,選出代價最低的物理執行計劃。
而代價估計的過程離不開基數估計,它利用各個表、列的統計信息,估算出各算子的輸入行數、選擇率等信息,提供給算子的代價模型,從而估算出查詢計劃的代價。
總結
以上是生活随笔為你收集整理的mysql cbo优化器_查询优化器介绍 - PolarDB-X 云原生分布式数据库 - 阿里云的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 5.5主从同步_MySQL5
- 下一篇: mysql insert replace