膚淺的聊聊 TiDB 掃表算子, 掃索引算子, 合取范式(CNF), 析取范式(DNF), skyline pruning


這一章主要涉及TiDB如下的源碼:

  1. 掃表算子怎樣轉換為掃索引算子;

  2. 怎樣把Selection算子的過濾條件化簡, 轉為區間掃描;

假設我們有一個表:

t1(
  id int primary key not null auto_increment,
  a int,
  b int,
  c varchar(256),
  index(a)
);

其中, id 是主鍵, a 是索引; 

我們執行如下的 sql:

select a from t1 where a=5 or ( a>5 and (a>6 and a <8)  and a<12);

這條 sql 的最終執行計划是這樣的:

+---------------+--------+-----------+-----------------------------------------------------------------------+
| id            | count  | task      | operator info                                                         |
+---------------+--------+-----------+-----------------------------------------------------------------------+
| IndexReader_6 | 260.00 | root      | index:IndexScan_5                                                     |
| └─IndexScan_5 | 260.00 | cop[tikv] | table:t1, index:a, range:[5,5], (6,8), keep order:false, stats:pseudo |
+---------------+--------+-----------+-----------------------------------------------------------------------+  

這是一個索引掃描的執行計划, 索引掃描區間是 [5,5], (6,8);

我們轉到源代碼, 看這樣的計划是怎樣生成的;

這是解析 sql 之后最初生成的執行計划:

在調用 logicalOptimize 函數做邏輯優化之后, 執行計划變為下面這樣:

Selection算子哪兒去了?

Selection算子被下推到了 DataSource 算子中, 在 DataSource 的 pushedDownConds 中保存着下推的過濾算子, 是這樣的:

這樣的一個遞歸的樹狀的過濾算子很難在索引掃描中使用, 因為索引底層是順序排列的, 所以要將這顆樹轉為掃描區間;

在物理優化中, 會調用 DetachCondAndBuildRangeForIndex 來生成掃描區間, 這個函數會遞歸的調用如下 2 個函數:

detachDNFCondAndBuildRangeForIndex, 展開 析取范式(DNF), 生成掃描區間或合並掃描區間;
detachCNFCondAndBuildRangeForIndex, 展開 合取范式(CNF), 生成掃描區間或合並掃描區間;

上面的表達式樹最終生成了這樣的區間: [5,5], (6,8) --- "[" 是開區間, "(" 是閉區間,  遞歸被消除了;

接下來, 這個索引掃描會加入到 DataSource 的備選的訪問表的方法中;

在 DataSource 的 possibleAccessPaths 里保存了訪問表的可能的方案, 這里是 2 個方案:

  1. 全表掃描, 用表達式樹進行過濾: a=5 or ( a>5 and (a>6 and a <8) and a<12);

  2. 掃索引 a 列, 執行區間掃描 [5,5], (6,8);

 

物理優化階段, 會從算子樹的根節點遞歸調用每個算子的 findBestTask 函數, DataSoure 算子會從 possibleAccessPaths  獲取最優的執行計划;

 

這里用到了 skyline pruning 算法, 從多個維度來判斷哪個執行計划更優, 最后用索引掃描算子替換掉 DataSource 算子;

最終生成了這樣的執行計划:

 

 結束;

 

 

 

 

 

 

 

 

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM