Without a global secondary index (GSI), a query that filters on a non-shard-key column must fan out to every table partition. A GSI solves this by maintaining an independent index table sharded on the index columns, so PolarDB-X can route the query directly to the relevant partitions instead of scanning all of them.
This topic covers DRDS mode tables. The same methods apply to AUTO mode tables; use the syntax described in CREATE INDEX (AUTO mode) instead.
GSI syntax
PolarDB-X extends the MySQL DDL syntax to support GSIs, using the same INDEX keyword convention as MySQL.
Define a GSI when creating a table:
Add a GSI after creating a table:
The syntax uses five components:
| Component | Description |
|---|---|
| Index name | The name of the GSI |
| Base table name | The host table of the GSI |
| Index column | The shard key of the GSI; includes all columns in the index sharding clause |
| Covering column | Additional columns stored in the index; defaults to the primary key and all shard keys of the base table |
| Sharding clause | The database and table sharding algorithm; uses the same syntax as the CREATE TABLE sharding clause |
For AUTO mode syntax, see CREATE TABLE (AUTO mode).
Create a GSI
Define a GSI at table creation
The following example creates the t_order table sharded by order_id, with g_i_seller as an inline GSI sharded by seller_id:
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`);Add a GSI to an existing table
The following example adds a unique GSI g_i_buyer on buyer_id with both database and table sharding:
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 3After the GSI is created, PolarDB-X verifies the index data before the DDL statement completes. To manually verify or repair index data, run CHECK GLOBAL INDEX.
Query with a GSI
Automatic index selection
PolarDB-X automatically selects the lowest-cost covering index for queries on tables with GSIs. Use EXPLAIN to confirm which index the optimizer selects:
EXPLAIN SELECT t_order.id, t_order.order_snapshot FROM t_order WHERE t_order.seller_id = 's1';Execution plan result:
IndexScan(tables="g_i_seller_sfL1_2", sql="SELECT `id`, `order_snapshot` FROM `g_i_seller` AS `g_i_seller` WHERE (`seller_id` = ?)")The optimizer selects g_i_seller because all queried columns (id, order_snapshot, and seller_id) are covered by the index, and the seller_id equality condition matches the index shard key — eliminating both a table lookup and a full partition scan.
If a query needs columns not in the index, PolarDB-X first queries the GSI for primary keys and base table shard keys, then fetches the missing columns from the base table. For details, see INDEX HINT.
Force a specific index
Use either of the following syntaxes to override automatic index selection:
FORCE INDEX:
FORCE INDEX({index_name})Example:
SELECT a.order_id FROM t_order a FORCE INDEX(g_i_seller) WHERE a.buyer_id = 123;TDDL hint:
/*+TDDL:INDEX({table_name/table_alias}, {index_name})*/Example:
/*+TDDL:index(a, g_i_buyer)*/ SELECT * FROM t_order a WHERE a.buyer_id = 123Ignore or suggest an index
IGNORE INDEX — exclude a specific index from consideration:
IGNORE INDEX({index_name},...)Example:
SELECT t_order.id, t_order.order_snapshot FROM t_order IGNORE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';USE INDEX — suggest a preferred index:
USE INDEX({index_name},...)Example:
SELECT t_order.id, t_order.order_snapshot FROM t_order USE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';Limitations
Limitations on creating GSIs
GSIs cannot be created on non-partitioned tables or broadcast tables.
Unique GSIs do not support prefix indexes.
An index table must have an explicit name.
An index table must specify a database sharding rule, or both a database and table sharding rule. Specifying only a table sharding rule is not supported.
The index keys of an index table must include all shard keys of the index table.
The same column cannot serve as both an index key column and a covering column.
By default, an index table contains the primary key columns and all shard key columns of the base table. Columns not specified as index key columns are used as covering columns.
In DRDS mode: if all index columns of a local index in the base table are present in the index table, the local index is automatically added to the index table.
If no local indexes exist on the index key columns of a GSI, a local index is automatically created for each index key column.
A GSI created on multiple columns automatically gets a composite index covering all index key columns.
The
Lengthparameter only specifies the prefix length of a sharding key for creating a local index.
Limitations on ALTER TABLE
The following matrix shows which ALTER TABLE column operations are supported for tables with GSIs.
| Clause | Change shard keys of the base table | Change the primary key | Change the unique column of a local index | Change shard keys of the index table | Change columns in the unique index | Change index columns | Change covering columns |
|---|---|---|---|---|---|---|---|
| ADD COLUMN | N/A | Not supported | N/A | N/A | N/A | N/A | N/A |
| ALTER COLUMN SET DEFAULT and ALTER COLUMN DROP DEFAULT | Supported | Supported | Supported | Supported | Supported | Supported | Supported |
| CHANGE COLUMN | Not supported | Not supported | Supported | Not supported | Supported* | Supported* | Supported* |
| DROP COLUMN | Not supported | Not supported | Supported only if the unique index covers one column | Not supported | Supported* | Supported* | Supported* |
| MODIFY COLUMN | Supported* (AUTO mode only) | Supported* | Supported | Supported* (AUTO mode only) | Supported* | Supported* | Supported* |
Supported\*: Only for instances that support lock-free column type changes.
Additional notes on ALTER TABLE:
To rename a GSI, drop it with DROP INDEX and recreate it. Renaming a GSI directly can degrade its performance. For assistance, contact us.
When a column belongs to multiple column types in the matrix above and an operation is unsupported for any one of those types, the operation cannot proceed.
The following table lists index management operations via ALTER TABLE:
| Statement | Support |
|---|---|
| ALTER TABLE ADD PRIMARY KEY | Supported |
| ALTER TABLE ADD [UNIQUE/FULLTEXT/SPATIAL/FOREIGN] KEY | Supported. Adds a local index to both the base table and index table simultaneously. The local index name must differ from the GSI name. |
| ALTER TABLE ALTER INDEX index_name {VISIBLE | INVISIBLE} | Supported on the base table only. Cannot change the status of a GSI. |
| ALTER TABLE {DISABLE | ENABLE} KEYS | Supported on the base table only. Cannot change the status of a GSI. |
| ALTER TABLE DROP PRIMARY KEY | Not supported |
| ALTER TABLE DROP INDEX | Supported. Drops only a common index or a GSI. |
| ALTER TABLE DROP FOREIGN KEY fk_symbol | Supported on the base table only. |
| ALTER TABLE RENAME INDEX | Supported |
Limitations on ALTER GSI TABLE
DDL and DML statements cannot be executed directly on a GSI.
DML statements with NODE HINTs cannot update the base table and GSIs simultaneously.
Other supported statements
The following statements work on tables that have GSIs:
| Statement | Supported |
|---|---|
| DROP TABLE | Yes |
| DROP INDEX | Yes |
| TRUNCATE TABLE | Yes |
| RENAME TABLE | Yes |
| ALTER TABLE RENAME | Yes |
FAQ
Why do I get "Does not support create Global Secondary Index on single or broadcast table"?
This error means the target table is a non-partitioned table or a broadcast table, which cannot have GSIs.
Check how the table was created:
Non-partitioned table (DRDS mode): Created in a single database with no sharding. See CREATE TABLE (DRDS mode).
Non-partitioned table (AUTO mode): Created with the
SINGLEkeyword. See CREATE TABLE (AUTO mode).Broadcast table: Created with the
BROADCASTkeyword; an identical copy of the table exists on each data node. See CREATE TABLE (DRDS mode) or CREATE TABLE (AUTO mode).
GSIs can only be created on partitioned, non-broadcast tables.