全部產品
Search
文件中心

PolarDB:自動FORCE INDEX

更新時間:Aug 01, 2024

本文為您介紹PolarDB-X的自動FORCE INDEX機制。

背景資訊

當一條查詢SQL(邏輯SQL)發往PolarDB-X時,PolarDB-X的計算節點的最佳化器會將其分成可下推和不可下推的兩部分,可下推的部分也被稱為物理SQL。大多數情況下,物理SQL會直接發送給儲存節點,由PolarDB-X的儲存節點基於代價選擇合適的局部索引。

由於代價模型缺陷、統計資訊不準確等問題,基於代價選擇索引的模式可能會出現索引選錯。因此在某些確定性情境下,計算節點會基於規則選擇合適的局部索引,使用FORCE INDEX指定索引將其添加到物理SQL中,幹預儲存節點的索引選擇,減少錯誤發生的機率。

支援版本

  • 對於5.4.18-17181576之前的執行個體,無自動FORCE INDEX機制。

  • 對於初次購買版本在5.4.18-17181576之前並升級到5.4.18-17181576及以上的執行個體,預設關閉自動FORCE INDEX機制。

  • 對於新購執行個體

    • 計算節點組件版本低於5.4.18,無自動FORCE INDEX機制。

    • 計算節點組件版本為5.4.18,小版本低於17181576,無自動FORCE INDEX機制;小版本不低於17181576,預設開啟自動FORCE INDEX機制。

    • 計算節點組件版本為5.4.19,發布日期早於2024-07-10之前,無自動FORCE INDEX機制;發布日期不早於2024-07-10,預設開啟自動FORCE INDEX機制。

    • 計算節點組件版本高於5.4.19,預設開啟自動FORCE INDEX機制。

說明

注意事項

  • 對於只涉及單表、廣播表的查詢,不會觸發自動FORCE INDEX。

  • 對於下推到儲存節點的多表關聯物理SQL,不會觸發自動FORCE INDEX。

  • 對於下推到單分區的查詢,不會觸發自動FORCE INDEX。

  • 局部索引選擇(local index selection)的優先順序從高到低,如下所示:

    • 手動FORCE INDEX。

    • 自動FORCE INDEX。

    • XPlan索引選擇。

    • 儲存節點索引選擇。

原理

主鍵索引和唯一索引

主鍵索引和唯一索引自動FORCE INDEX的條件如下:

  • 收集等值條件的列,收集到的列都是表中的原始列。

  • 主鍵索引或唯一索引被收集到的列覆蓋。

普通二級索引

普通二級索引自動FORCE INDEX的條件如下:

  • 剔除不能利用索引的條件後,剩餘條件僅包含等值條件。

  • 收集等值條件與ORDER BY的列,收集到的列都是表中的原始列。

  • 收集到的列被索引首碼覆蓋。

樣本

樣本表example,包含唯一索引UK與聯合索引LK,樣本如下:

CREATE TABLE `example` (
	`a` int(11) NOT NULL,
	`b` int(11) NOT NULL,
	`c` int(11) NOT NULL,
	`d` int(11) NOT NULL,
	UNIQUE KEY `UK` (`a`, `b`),
	KEY `LK` (`b`, `c`, `d`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`a`)
PARTITIONS 4

情境一:

收集到的列為(a,b),c,可以覆蓋索引UK,會自動執行FORCE INDEX(UK),樣本如下:

select * from example where (a,b) in ((1,2),((3,4))) and c = 1 order by d
mysql> explain select * from example where (a,b) in ((1,2),((3,4))) and c = 1 order by d;
+------------------------+
| LOGICAL EXECUTIONPLAN                                                      
+------------------------+
| MergeSort(sort="d ASC")                                                    
|   LogicalView(tables="example[p1,p4]", shardCount=2, sql="SELECT `a`, `b`, `c`, `d` FROM `example` AS `example` FORCE INDEX(UK) WHERE ((((`a`, `b`)) IN(?)) AND (`c` = ?)) ORDER BY `d`", pruningInfo="all size:2*2(part), pruning size:2") |
| HitCache:false                                                             
| Source:PLAN_CACHE                                                          
| TemplateId: 3148a498                                                       
+------------------------+

情境二:

收集到的列為c,不可以覆蓋索引UK,不會自動執行FORCE INDEX(),樣本如下:

select * from example where (a+1,b) in ((1,2),((3,4))) and c = 1 order by d
mysql> explain select * from example where (a+1,b) in ((1,2),((3,4))) and c = 1 order by d;
+------------------------+
| LOGICAL EXECUTIONPLAN    
+------------------------+
| MergeSort(sort="d ASC")       
|   LogicalView(tables="example[p1,p2,p3,p4]", shardCount=4, sql="SELECT `a`, `b`, `c`, `d` FROM `example` AS `example` WHERE (((((`a` + ?), `b`)) IN(?)) AND (`c` = ?)) ORDER BY `d`") |
| HitCache:false            
| Source:PLAN_CACHE       
| TemplateId: 5ad46a6e  
+------------------------+

情境三:

收集到的列為b,c,可以被索引LK首碼匹配,會自動執行FORCE INDEX(LK),樣本如下:

select * from example where (b) in (1,2) and a > b order by c
mysql> explain select * from example where (b) in (1,2) and a > b order by c;
+------------------------+
| LOGICAL EXECUTIONPLAN  
+------------------------+
| MergeSort(sort="c ASC") 
|   LogicalView(tables="example[p1,p2,p3,p4]", shardCount=4, sql="SELECT `a`, `b`, `c`, `d` FROM `example` AS `example` FORCE INDEX(LK) WHERE ((`a` > `b`) AND (`b` IN(?))) ORDER BY `c`") |
| HitCache:false          
| Source:PLAN_CACHE       
| TemplateId: 3a4124bd    
+------------------------+

情境四:

剔除不能利用索引的條件後,剩餘條件包含非等值條件c>1,不會自動執行FORCE INDEX,樣本如下:

select * from example where (b) in (1,2) and c > 1 order by d
mysql> explain select * from example where (b) in (1,2) and c > 1 order by d;
+------------------------+
| LOGICAL EXECUTIONPLAN
+------------------------+
| MergeSort(sort="d ASC")
|   LogicalView(tables="example[p1,p2,p3,p4]", shardCount=4, sql="SELECT `a`, `b`, `c`, `d` FROM `example` AS `example` WHERE ((`b` IN(?)) AND (`c` > ?)) ORDER BY `d`") |
| HitCache:false                                                                
| Source:PLAN_CACHE                                                             
| TemplateId: f01b447f                                                          
+------------------------+