日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

查詢優化器介紹

查詢優化器負責優化邏輯計劃從而輸出物理計劃,其主要階段包含查詢改寫和計劃枚舉。本文將介紹查詢優化器的基本原理,以及什么是關系代數運算符、查詢改寫(RBO階段)和查詢計劃枚舉(CBO階段)。

PolarDB-X接收到一條SQL后的執行過程大致如下:查詢優化器

  • 語法解析器(Parser)將SQL文本解析成抽象語法樹(AST)。

  • 語法樹被轉化成基于關系代數的邏輯計劃。

  • 查詢優化器(Optimizer)對邏輯計劃進行優化得到物理計劃。

  • 查詢執行器(Executor)執行該計劃,得到查詢結果并返回給客戶端。

關系代數運算符

關系代數算子

一條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。

例如,對于如下查詢SQL:

SELECT l_orderkey, sum(l_extendedprice *(1 - l_discount)) AS revenue
FROM CUSTOMER, ORDERS, LINEITEM
WHERE c_mktsegment = 'AUTOMOBILE'
  and c_custkey = o_custkey
  and l_orderkey = o_orderkey
  and o_orderdate < '1995-03-13'
  and l_shipdate > '1995-03-13'
GROUP BY l_orderkey;

通過EXPLAIN命令看到該SQL的執行計劃如下:

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執行:

    explain  select id from t1 where id in (select id from t2 where t2.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執行,過濾掉不需要的行和列。

    JOINClustering

    將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的過程包括以下幾個步驟:

  1. 搜索引擎利用轉化規則,對輸入的邏輯執行計劃進行變換,構造出物理執行計劃的搜索空間。

  2. 利用代價模型對搜索空間中的每一個執行計劃進行代價估計,選出代價最低的物理執行計劃。

  3. 代價估計的過程離不開基數估計,它利用各個表、列的統計信息,估算出各物理算子的輸入行數、選擇率等信息,提供給物理算子的代價模型,從而估算出查詢計劃的代價。