Dalam database ter-shard, data didistribusikan ke shard fisik berdasarkan kunci shard. Kueri yang melakukan filter pada kolom selain kunci shard memaksa PolarDB-X untuk memindai setiap shard—pemindaian seluruh shard yang semakin mahal seiring pertambahan volume data. Indeks sekunder global (GSI) mengatasi masalah ini dengan memelihara tabel indeks terpisah yang di-shard berdasarkan kolom yang diindeks, sehingga pengoptimal dapat mengarahkan kueri langsung ke shard yang relevan.
Topik ini menjelaskan cara membuat dan menggunakan GSI untuk mempercepat kueri di PolarDB-X.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
MySQL 5.7 atau versi yang lebih baru
Versi minor kernel PolarDB-X 5.4.1 atau versi yang lebih baru
Cara kerja GSI
GSI terdiri dari komponen-komponen berikut:
| Komponen | Deskripsi |
|---|---|
| Index table | Tabel terdistribusi terpisah yang dibuat untuk GSI, di-shard secara independen dari tabel utama menggunakan kolom yang diindeks sebagai kunci shard-nya. |
| Index column | Kunci shard dari tabel indeks. Semua kolom yang dirujuk dalam klausa sharding menjadi kolom indeks. |
| Covering column | Kolom tambahan yang disimpan dalam tabel indeks selain kolom indeks. Secara default, kunci utama dan semua kunci shard dari tabel utama disertakan. Ketika semua kolom yang dibutuhkan oleh kueri tersedia di tabel indeks, PolarDB-X membaca langsung dari tabel indeks tanpa perlu lookup ke tabel utama — ini disebut pembacaan indeks cakupan (covering index read). |
| Sharding clause | Menentukan cara tabel indeks didistribusikan ke partisi database dan tabel. Sintaksnya sama dengan klausa sharding pada CREATE TABLE. |
Kapan menggunakan GSI: Buat GSI ketika kueri sering melakukan filter pada kolom yang bukan kunci shard tabel utama, dan pemindaian seluruh shard menyebabkan masalah performa. Jika sebagian besar kueri menggunakan kunci shard secara langsung, GSI hanya menambah beban penyimpanan dan penulisan tanpa memberikan manfaat.
Buat GSI
PolarDB-X memperluas sintaks bahasa definisi data (DDL) MySQL untuk mendukung definisi GSI. Sintaksnya mengikuti pola yang sama dengan pembuatan indeks standar MySQL.
Ada dua cara untuk menambahkan GSI:
Definisikan GSI secara inline saat membuat tabel
Tambahkan GSI ke tabel yang sudah ada dengan
CREATE GLOBAL INDEX
Contoh berikut menggunakan tabel t_order yang di-shard berdasarkan order_id. Tabel tersebut juga memiliki kolom buyer_id dan seller_id yang sering digunakan sebagai filter dalam kueri, sehingga menjadi kandidat yang baik untuk GSI.
-- Definisikan GSI saat membuat tabel
CREATE TABLE t_order (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
GLOBAL INDEX `g_i_seller`(`seller_id`) COVERING (`id`, `order_id`, `buyer_id`, `order_snapshot`) dbpartition by hash(`seller_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);
-- Tambahkan GSI ke tabel yang sudah ada
CREATE UNIQUE GLOBAL INDEX `g_i_buyer` ON `t_order`(`buyer_id`)
COVERING(`seller_id`, `order_snapshot`)
dbpartition by hash(`buyer_id`) tbpartition by hash(`buyer_id`) tbpartitions 3Untuk sintaks lengkap dan opsi pembuatan GSI, lihat CREATE INDEX.
Gunakan GSI
Setelah GSI dibuat, kueri dapat menggunakannya melalui tiga cara: pemilihan otomatis oleh pengoptimal, sintaks HINT eksplisit, atau kueri langsung ke tabel indeks.
Pemilihan indeks otomatis
Untuk kueri pada tabel utama yang memiliki GSI yang sesuai, PolarDB-X secara otomatis memilih indeks dengan biaya terendah. Hanya indeks cakupan (covering index) yang memenuhi syarat untuk pemilihan otomatis—jika tabel indeks tidak berisi semua kolom yang dibutuhkan oleh kueri, pengoptimal tidak akan memilihnya secara otomatis.
Pada contoh berikut, kueri melakukan filter berdasarkan seller_id dan memilih id serta order_snapshot. Karena g_i_seller mencakup ketiga kolom tersebut dan seller_id merupakan kunci shard-nya, pengoptimal mengarahkan kueri langsung ke tabel indeks, sehingga menghindari pemindaian penuh pada shard utama t_order:
EXPLAIN SELECT t_order.id, t_order.order_snapshot FROM t_order WHERE t_order.seller_id = 's1';
IndexScan(tables="g_i_seller_sfL1_2", sql="SELECT `id`, `order_snapshot` FROM `g_i_seller` AS `g_i_seller` WHERE (`seller_id` = ?)")Tentukan indeks dengan HINT
Gunakan petunjuk indeks (index hints) untuk mengganti pilihan pengoptimal. PolarDB-X mendukung dua bentuk HINT:
`FORCE INDEX` — Memaksa kueri menggunakan indeks yang ditentukan:
SELECT a.*, b.order_id
FROM t_seller a
JOIN t_order b FORCE INDEX(g_i_seller) ON a.seller_id = b.seller_id
WHERE a.seller_nick = "abc";TDDL hint — Menentukan indeks menggunakan direktif komentar:
/*+TDDL:INDEX({table_name/table_alias}, {index_name})*/Contoh:
/*+TDDL:index(a, g_i_buyer)*/ SELECT * FROM t_order a WHERE a.buyer_id = 123Jika kueri membutuhkan kolom yang tidak tersimpan di tabel indeks, PolarDB-X melakukan lookup dua langkah: pertama meminta kunci utama dan kunci shard tabel utama dari tabel indeks, lalu mengambil kolom sisanya dari tabel utama. Untuk detailnya, lihat INDEX HINT.
Kueri langsung ke tabel indeks
Jika tabel indeks berisi semua kolom yang dibutuhkan oleh kueri, Anda dapat melakukan kueri langsung ke tabel indeks untuk mendapatkan hasil tanpa melibatkan tabel utama.
Kontrol pemilihan indeks dengan USE INDEX dan IGNORE INDEX
Gunakan USE INDEX untuk membatasi pengoptimal hanya pada kumpulan indeks tertentu, atau IGNORE INDEX untuk mengecualikan indeks dari pertimbangan:
-- Cegah pengoptimal menggunakan g_i_seller
SELECT t_order.id, t_order.order_snapshot FROM t_order IGNORE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';
-- Batasi pengoptimal hanya mempertimbangkan g_i_seller
SELECT t_order.id, t_order.order_snapshot FROM t_order USE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';Keduanya menerima daftar nama indeks yang dipisahkan koma: IGNORE INDEX(index1, index2, ...).
Langkah selanjutnya
CREATE INDEX — Referensi sintaks lengkap pembuatan GSI
INDEX HINT — Panduan lengkap mengenai sintaks dan perilaku petunjuk indeks