このトピックでは、PolarDB-XのFORCE INDEXの制限と使用方法について説明します。
背景情報
PolarDB-Xは、グローバルセカンダリインデックスとローカルインデックスの両方をサポートします。 ローカルインデックスは、テーブル上に直接作成することも、グローバルセカンダリインデックスのインデックスパーティションとして作成することもできます。 PolarDB-Xは、2レベルのインデックスのサポートを追加することで、MySQLのFORCE INDEXとUSE INDEXの機能を拡張します。つまり、ヒントでグローバルインデックスとローカルインデックスの両方を指定できます。
サポートされているバージョン
計算ノードのバージョンが5.4.18より前の場合、単一レベルのインデックスのみがサポートされます。
計算ノードのバージョンが5.4.18で、マイナーバージョンが1718157より前の場合、単一レベルのインデックスのみがサポートされます。
計算ノードのバージョンが5.4.18で、マイナーバージョンが1718157以降の場合、2レベルのインデックスがサポートされます。
計算ノードのバージョンが5.4.19で、リリース日が2024 7月10日より前の場合、単一レベルのインデックスのみがサポートされます。
コンピュートノードのバージョンが5.4.19で、リリース日が2024年7月10日以降の場合、2レベルのインデックスがサポートされます。
計算ノードのバージョンが5.4.19以降の場合、2レベルのインデックスがサポートされます。
インスタンスのバージョンを表示する方法については、「インスタンスのバージョンの表示と更新」をご参照ください。
インスタンスのバージョン管理については、「リリースノート」をご参照ください。
使用上の注意
FORCE INDEXまたはINDEX HINTを使用する場合は、完全な名前でインデックスを指定する必要があります。 プレフィックス一致はサポートされていません
次の条件が満たされると、指定されたローカルインデックスが強制的に使用されます。
これは、コスト推定に基づいてオプティマイザによって選択されるグローバルセカンダリインデックスのインデックスパーティションです。
注: 指定されたローカルインデックスパーティションを含まないグローバルセカンダリインデックスは選択されません。
FORCE INDEX (PRIMARY) を使用すると、すべてのグローバルセカンダリインデックスが選択されません。
構文
単一レベルのインデックス
# FORCE INDEX
tbl_name [[AS] alias] [index_hint]
index_hint:
FORCE INDEX({gsi_name|local_index_name|primary})
# INDEX HINT
/*+TDDL: INDEX({table_name|table_alias}, {local_index_name|gsi_name|primary})*/パラメーター
gsi_name: グローバルセカンダリインデックスの名前。
local_index_name: ローカルインデックスの名前。
primary: 主キー。
2レベルのインデックス
# FORCE INDEX
tbl_name [[AS] alias] [index_hint]
index_hint:
FORCE INDEX(gsi_name[.{local_index_name|primary}] | local_index_name | primary[.{local_index_name|primary}])
# INDEX HINT
/*+TDDL: INDEX({table_name|table_alias}, {local_index_name|gsi_name|primary} [, {local_index_name|primary}])*/パラメーター
gsi_name: グローバルセカンダリインデックスの名前。
local_index_name: ローカルインデックスの名前。
primary: 主キー。
例
CREATE TABLE `t_order` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) NOT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (`order_id`)
PARTITION BY KEY(`buyer_id`)
PARTITIONS 16,
GLOBAL INDEX `g_i_seller` (`seller_id`) COVERING (`order_id`)
PARTITION BY KEY(`seller_id`)
PARTITIONS 16,
KEY `l_i_order` (`order_id`),
KEY `l_i_buyer` (`buyer_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8
PARTITION BY KEY(`order_id`)
PARTITIONS 16単一レベルのインデックス
FORCE indexでローカルインデックスl_i_orderを指定します。
mysql> EXPLAIN SELECT * FROM T_ORDER FORCE INDEX(l_i_order);
+---------------------+
| LOGICAL EXECUTIONPLAN
+---------------------+
| Gather(concurrent=true)
| LogicalView(tables="t_order[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `buyer_id`, `seller_id` FROM `T_ORDER` AS `T_ORDER` FORCE INDEX(L_I_ORDER)")
| HitCache:false
| Source:PLAN_CACHE
| TemplateId: 3d1b35fa
+---------------------+index HINTでグローバルセカンダリインデックスg_i_buyerを指定します。
mysql> EXPLAIN /*TDDL:INDEX(T_ORDER, g_i_buyer)*/ SELECT * FROM T_ORDER;
+---------------------+
| LOGICAL EXECUTIONPLAN
+---------------------+
| Project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id")
| BKAJoin(condition="id = id AND order_id = order_id", type="inner")
| Gather(concurrent=true)
| IndexScan(tables="g_i_buyer_$27c2[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `buyer_id` FROM `g_i_buyer_$27c2` AS `g_i_buyer_$27c2`")
| Gather(concurrent=true)
| LogicalView(tables="t_order[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `seller_id` FROM `T_ORDER` AS `T_ORDER` FORCE INDEX(PRIMARY) WHERE (((`id`, `order_id`)) IN (...))")
| HitCache:false
| Source:null
| TemplateId: NULL
+---------------------+2レベルのインデックス
ローカルインデックスauto_shard_key_buyer_idを指定します。これは、グローバルセカンダリインデックスg_i_buyerの一部です。強制インデックス:
mysql> EXPLAIN SELECT * FROM T_ORDER FORCE INDEX(g_i_buyer.auto_shard_key_buyer_id);
+---------------------+
| LOGICAL EXECUTIONPLAN
+---------------------+
| Project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id")
| BKAJoin(condition="id = id AND order_id = order_id", type="inner")
| Gather(concurrent=true)
| IndexScan(tables="g_i_buyer_$27c2[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `buyer_id` FROM `g_i_buyer_$27c2` AS `g_i_buyer_$27c2` FORCE INDEX(AUTO_SHARD_KEY_BUYER_ID)")
| Gather(concurrent=true)
| LogicalView(tables="t_order[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `seller_id` FROM `T_ORDER` AS `T_ORDER` FORCE INDEX(PRIMARY) WHERE (((`id`, `order_id`)) IN (...))")
| HitCache:false
| Source:PLAN_CACHE
| TemplateId: ae278c70
+---------------------+INDEX HINTを使用して、ローカルインデックスauto_shard_key_seller_idを指定します。これは、t1という名前のテーブルのグローバルセカンダリインデックスg_i_sellerと、t2という名前のテーブルのローカルインデックスL_I_ORDERの一部です。
mysql> EXPLAIN /*TDDL:index(t1, g_i_seller, auto_shard_key_seller_id) index(t2, primary, L_I_ORDER)*/ SELECT * FROM t_order t1 join t_order t2 on t1.id=t2.id where t1.buyer_id = '123456';
+---------------------+
| LOGICAL EXECUTIONPLAN
+---------------------+
| BKAJoin(condition="id = id", type="inner")
| Project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id")
| BKAJoin(condition="id = id AND order_id = order_id", type="inner")
| Gather(concurrent=true)
| IndexScan(tables="g_i_seller_$3e3d[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `seller_id` FROM `g_i_seller_$3e3d` AS `g_i_seller_$3e3d` FORCE INDEX(AUTO_SHARD_KEY_SELLER_ID)")
| Gather(concurrent=true)
| LogicalView(tables="t_order[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `buyer_id` FROM `t_order` AS `t_order` FORCE INDEX(PRIMARY) WHERE ((`buyer_id` = ?) AND (((`id`, `order_id`)) IN (...)))")
| Gather(concurrent=true)
| LogicalView(tables="t_order[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `order_id`, `buyer_id`, `seller_id` FROM `t_order` AS `t_order` FORCE INDEX(L_I_ORDER) WHERE (`id` IN (...))")
| HitCache:false
| Source:null
| TemplateId: NULL
+---------------------+