Topik ini menjelaskan batasan dan penggunaan FORCE INDEX di PolarDB-X.
Informasi latar belakang
PolarDB-X mendukung indeks sekunder global dan indeks lokal. Indeks lokal dapat dibuat langsung pada tabel atau sebagai partisi indeks dari indeks sekunder global. PolarDB-X memperluas fungsionalitas FORCE INDEX dan USE INDEX di MySQL dengan menambahkan dukungan untuk indeks dua tingkat, yang berarti Anda dapat menentukan baik indeks global maupun lokal dalam petunjuk (hints).
Versi yang didukung
Jika versi node komputasi lebih awal dari 5.4.18, hanya indeks satu tingkat yang didukung.
Jika versi node komputasi adalah 5.4.18 dan versi minor lebih awal dari 1718157, hanya indeks satu tingkat yang didukung.
Jika versi node komputasi adalah 5.4.18 dan versi minor adalah 1718157 atau lebih baru, indeks dua tingkat didukung.
Jika versi node komputasi adalah 5.4.19 dan tanggal rilis lebih awal dari 10 Juli 2024, hanya indeks satu tingkat yang didukung.
Jika versi node komputasi adalah 5.4.19 dan tanggal rilis adalah 10 Juli 2024 atau lebih baru, indeks dua tingkat didukung.
Jika versi node komputasi lebih baru dari 5.4.19, indeks dua tingkat didukung.
Untuk informasi tentang cara melihat versi suatu instance, lihat Lihat dan Perbarui Versi Suatu Instance.
Untuk informasi tentang penomoran versi instance, lihat Catatan Rilis.
Catatan penggunaan
Saat menggunakan FORCE INDEX atau INDEX HINT, Anda harus menentukan indeks dengan nama lengkapnya. Pencocokan awalan tidak didukung.
Indeks lokal yang ditentukan akan dipaksa digunakan jika kondisi berikut terpenuhi:
Ini adalah partisi indeks dari indeks sekunder global yang dipilih oleh optimizer berdasarkan estimasi biaya.
Catatan: Indeks sekunder global yang tidak mengandung partisi indeks lokal yang ditentukan tidak akan dipilih.
Saat FORCE INDEX (PRIMARY) digunakan, semua indeks sekunder global tidak akan dipilih.
Sintaksis
Indeks satu tingkat
# 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})*/Parameter
gsi_name: nama indeks sekunder global.
local_index_name: nama indeks lokal.
primary: kunci utama.
Indeks dua tingkat
# 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}])*/Parameter
gsi_name: nama indeks sekunder global.
local_index_name: nama indeks lokal.
primary: kunci utama.
Contoh
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 16Indeks satu tingkat
Tentukan indeks lokal l_i_order dalam FORCE INDEX:
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
+---------------------+Tentukan indeks sekunder global g_i_buyer dalam INDEX HINT:
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
+---------------------+Indeks dua tingkat
Tentukan indeks lokal auto_shard_key_buyer_id, yang merupakan bagian dari indeks sekunder global g_i_buyer, dalam FORCE INDEX:
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
+---------------------+Gunakan INDEX HINT untuk menentukan indeks lokal auto_shard_key_seller_id, yang merupakan bagian dari indeks sekunder global g_i_seller pada tabel dengan nama panggilan t1, dan indeks lokal L_I_ORDER pada tabel dengan nama panggilan t2.
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
+---------------------+