This topic describes how to create and use global secondary indexes (GSIs) for tables in DRDS mode.
The methods in this topic also apply to tables in AUTO mode. However, you must use the syntax described in CREATE INDEX (AUTO mode).
Gsi syntax structure
PolarDB-X extends the MySQL DDL syntax to support creating GSIs, which is the same as creating indexes in MySQL.
Define a GSI when creating a table
Add a GSI after creating a table
Index name: The name of the GSI.
Base table name: The host table of the GSI.
Index column: The shard key of the GSI, which includes all columns used in the index sharding clause.
Covering column: Other columns in the GSI. By default, this includes the primary key and all shard keys of the primary table.
Sharding clause: The database and table sharding algorithm of the GSI. The syntax is consistent with the sharding clause in the
CREATE TABLE
statement.The preceding variables for creating a GSI in a table in DRDS mode. For more information about creating a GSI in a table in AUTO mode, see CREATE TABLE (AUTO mode).
Constraints
Constraints on creating GSIs
GSIs cannot be created on single tables or broadcast tables.
Prefix indexes cannot be used in UNIQUE GSIs in any way.
An index name must be specified when creating a GSI.
When creating a GSI, you must specify either a database sharding rule or a combination of database and table sharding rules. Specifying only a table sharding rule or no sharding rule is not allowed.
The index columns of a GSI must include all shard keys.
In the GSI definition clause, index columns and covering columns cannot be duplicated.
A GSI includes all primary keys and shard keys of the primary table by default. If they are not explicitly included in the index columns, they are added to the covering columns by default.
In a DRDS mode database, for each local index of the primary table, if all referenced columns are included in the GSI, the local index is added to the GSI by default.
For each index column of a GSI, if no index already exists, a separate index is created by default.
For a GSI with multiple index columns, a combined local index that includes all index columns is created by default.
In the index definition, the
Length
parameter of the index column is only used to create a local index on the GSI shard key.When creating a GSI after creating a table, data verification is automatically performed at the end of GSI creation. The DDL statement for creating the GSI is successful only if the verification passes.
NoteYou can also use CHECK GLOBAL INDEX to verify or correct index data.
Constraints on ALTER TABLE
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 of the table | 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 is created only on one column | Not supported | Supported* | Supported* | Supported* |
MODIFY COLUMN | Supported* (only in AUTO mode) | Supported* | Supported | Supported* (only in AUTO mode) | Supported* | Supported* | Supported* |
Supported*: Indicates that only instances that meet the conditions for supporting lock-free column type changes are supported.
Considering the stability and performance of global secondary indexes, directly using the DROP COLUMN command to delete columns in a global secondary index is currently prohibited. If you need to delete certain columns in a global secondary index, you can first use DROP INDEX to delete the corresponding global secondary index, then create a new secondary index, or contact us for technical support.
The above column classifications overlap (for example, index columns include global secondary index shard keys, and covering columns include primary table shard keys, primary keys, and specified columns). In case of conflicting support situations, "not supported" takes precedence over "supported".
The following table describes the ALTER TABLE
statements that you can use to manage indexes.
Statement | Description |
ALTER TABLE ADD PRIMARY KEY | Supported. |
ALTER TABLE ADD [UNIQUE/FULLTEXT/SPATIAL/FOREIGN] KEY | Supported. You can use this statement to add a local index on the base table and the index table at the same time. The name of the local index cannot be the same as the name of the GSI. |
ALTER TABLE ALTER INDEX index_name {VISIBLE | INVISIBLE} | Supported. It can only be used on the base table, rather than changing the GSI status. |
ALTER TABLE {DISABLE | ENABLE} KEYS | Supported. It can only be used on the base table, rather than changing the GSI status. |
ALTER TABLE DROP PRIMARY KEY | Not supported. |
ALTER TABLE DROP INDEX | Supported. It can only be used to delete regular indexes or GSIs. |
ALTER TABLE DROP FOREIGN KEY fk_symbol | Supported. It can only be used on the base table. |
ALTER TABLE RENAME INDEX | Supported. |
Constraints on ALTER GSI TABLE
DDL and DML statements cannot be executed on GSIs.
DML statements with NODE HINTs cannot update the base table and GSIs.
Other constraints
Statement | Supported in tables with GSIs |
Yes | |
Yes | |
Yes | |
Yes | |
ALTER TABLE RENAME | Yes |
Examples
Create a GSI.
-- Define a GSI when creating a table 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 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 3
Use the GSI in queries.
Specify an index using HINT
You can choose either of the following two HINT statements to specify the target index for the query.
FORCE INDEX({index_name})
Example:
SELECT a.order_id FROM t_order a FORCE INDEX(g_i_seller) WHERE a.buyer_id = 123;
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 = 123
NoteIf a query needs to use columns not included in the index, the GSI is first queried to obtain the primary keys and primary table shard keys of all records, and then the primary table is queried to obtain the values of the missing columns. For more information, see INDEX HINT.
Index selection query example:
For queries on a primary table with GSIs, PolarDB-X automatically selects the GSI that the optimizer considers to have the lowest cost (only covering index selection is supported).
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` = ?)")
NoteThe primary table in the above SQL query is
t_order
, with an equality filter condition onseller_id
, and the columns involved (id
,order_snapshot
, andseller_id
) are covered byg_i_seller
. Selecting the covering indexg_i_seller
both avoids table lookups and clearly reduces the number of table partitions to scan (seller_id
is the shard key ofg_i_seller
).In the execution plan result, you can see that the PolarDB-X optimizer has selected
g_i_seller
.
IGNORE INDEX
Syntax:
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
Syntax:
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';