このトピックでは、PolarDB-Xの自動FORCE INDEXメカニズムについて説明します。
背景情報
PolarDB-Xがクエリを受信すると、コンピュートノードのオプティマイザはクエリを2つの部分に分割します。 プッシュダウンできる部分は、物理SQLに変換されます。 通常、物理SQLは、コストに基づいて適切なローカルインデックスが選択されるデータノードに送信される。
しかしながら、選択されたインデックスは、コストモデルの欠陥または不正確な統計のために常に最適であるとは限らない。 したがって、特定の状況では、計算ノード上のオプティマイザは、使用される最適なローカルインデックスを決定し、FORCE indexヒントを使用して物理SQLでそれを指定します。 このような自動FORCE INDEXメカニズムは、間違ったインデックスを選択するリスクを最小限に抑える。
バージョン要件
このメカニズムをサポートするには、インスタンスのバージョンが5.4.18-17181576以降である必要があります。
5.4.18-17181576以降にアップグレードされた既存のインスタンスの場合、このメカニズムはサポートされますが、デフォルトでは無効になります。
新しく作成したインスタンスの場合:
計算ノードのバージョンが5.4.18以前の場合、このメカニズムはサポートされません。
計算ノードのバージョンが5.4.18で、マイナーバージョンが17181576より前の場合、このメカニズムはサポートされません。 計算ノードのバージョンが5.4.18で、マイナーバージョンが17181576または遅い場合、メカニズムはデフォルトで有効になります。
計算ノードのバージョンが5.4.19で、リリース日が2024 7月10日より前の場合、このメカニズムはサポートされません。 コンピュートノードのバージョンが5.4.19で、リリース日が7月10、2024日以降の場合、メカニズムはデフォルトで有効になっています。
計算ノードのバージョンが5.4.19以降の場合、メカニズムはデフォルトで有効になっています。
インスタンスのバージョンを表示する方法については、「インスタンスのバージョンの表示と更新」をご参照ください。
インスタンスのバージョン管理については、「リリースノート」をご参照ください。
使用上の注意
単一のテーブルまたはブロードキャストテーブルのクエリは、自動FORCE INDEXメカニズムをトリガーしません。
テーブルを結合する物理SQLは、自動FORCE INDEXメカニズムをトリガーしません。
単一のシャードにプッシュダウンされたクエリは、自動FORCE INDEXメカニズムをトリガーしません。
ローカルインデックスは、次のメカニズムによって優先度の高い順に選択されます。
マニュアルFORCE INDEX
自動フォースインデックス
XPlan
データノードによるインデックスの選択
自動FORCE INDEXの仕組み
主キーインデックスと一意インデックス
次の条件が満たされると、主キーインデックスまたは一意インデックスを自動的に使用することができます。
等価条件で使用される列は、オプティマイザによって収集され、元の列です。
収集された列は、主キーインデックスまたは一意のインデックスをカバーします。
共通セカンダリインデックス
次の条件が満たされると、共通のセカンダリインデックスを自動的に使用することができます。
クエリには、等価条件とインデックスを使用できない条件のみが含まれます。
等価条件で使用される列とORDER BY句で言及される列は、オプティマイザによって収集され、元の列です。
収集された列は、インデックスプレフィックスでカバーされます。
例:
一意のインデックス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
シナリオ1
オプティマイザは、一意のインデックスUK
をカバーする列 (a,b)
およびc
を収集しました。 英国
は自動的に使用を余儀なくされます。
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
+------------------------+
シナリオ 2
オプティマイザは、一意のインデックスUK
をカバーしていない列c
を収集しました。 英国
は使用を余儀なくされていません。
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
+------------------------+
シナリオ 3
オプティマイザは、インデックスLK
のプレフィックスと一致する列b
とc
を収集しました。 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
+------------------------+
シナリオ 4
インデックスを使用できない条件に加えて、クエリには非等価条件c>1
が含まれます。 インデックスは使用されません。
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
+------------------------+