PolarDB-X 1.0支持全局二級索引,本文將介紹如何創建、使用全局二級索引功能。
前提條件
使用限制
關于創建和使用GSI的相關限制,請參見使用全局二級索引時的注意事項。
創建GSI
PolarDB-X 1.0對MySQL DDL語法進行了擴展,增加定義GSI的語法。使用方式與在MySQL上創建索引一致。
- 建表時定義GSI
- 建表后添加GSI
說明
- 索引名:作為索引表的名字,用于創建索引表。
- 索引列:索引表的分庫分表鍵,即索引分庫分表子句中用到的所有列。
- 覆蓋列:索引表中的其他列,默認包含主鍵和主表的全部分庫分表鍵。
- 索引分庫分表子句:索引表的分庫分表算法,與CREATE TABLE中分庫分表子句的語法一致。
示例
# 建表時定義 GSI
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`);
# 添加 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
說明 更多關于創建全局二級索引的詳情,請參見CREATE INDEX。
使用GSI
GSI創建完成后,可以通過如下方式指定查詢使用索引表:
- 通過HINT指定索引
您可以選擇以下兩種HINT語句中的任意一種指定使用目標索引進行查詢。
- 語句:
FORCE INDEX({index_name})
示例: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:INDEX({table_name/table_alias}, {index_name})*/
示例:/*+TDDL:index(a, g_i_buyer)*/ SELECT * FROM t_order a WHERE a.buyer_id = 123
說明 如果查詢需要使用索引中未包含的列,則首先查詢索引表取得所有記錄的主鍵和主表分庫分表鍵,然后回查主表中取得缺少列的值,詳細說明請參見INDEX HINT。
- 語句:
- 直接查詢索引表
如果索引表中包含了查詢需要的所有列,可以直接查詢索引表獲得結果。
- 索引選擇
對于帶有全局二級索引的主表查詢,PolarDB-X 1.0會自動選擇出優化器認為代價最低的索引表(目前只支持覆蓋索引選擇)。
下面SQL查詢的主表是
t_order
,帶有seller_id
等值過濾條件,同時涉及的id
、order_snapshot
和seller_id
等列被全局二級索引g_i_seller
覆蓋。選擇了覆蓋索引g_i_seller
既可以不回表,又可以明確減少分表的掃描數目(seller_id
是g_i_seller
的拆分鍵)。通過EXPLAIN可以看到PolarDB-X 1.0優化器確實選擇了g_i_seller
。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` = ?)")
- IGNORE INDEX與USE INDEX
您可以通過以下HINT指定優化器使用或不使用某些索引。
- 語句:
IGNORE INDEX({index_name},...)
示例:
SELECT t_order.id,t_order.order_snapshot FROM t_order IGNORE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';
- 語句:
USE INDEX({index_name},...)
示例:SELECT t_order.id,t_order.order_snapshot FROM t_order USE INDEX(g_i_seller) WHERE t_order.seller_id = 's1';
- 語句: