PolarDB MySQL版支持在分区表上创建全局二级索引(Global Secondary Index,简称GSI)。使用全局二级索引可以实现透明分区表,即您可以像使用单表一样使用分区表,大大减少分区键对分区表的使用限制。
全局二级索引功能当前处于灰度发布阶段,如有需求,请前往配额中心,根据配额ID
polardb_mysql_gsi
找到配额名称,在对应的操作列单击申请来开通该功能。如需了解更多关于全局二级索引(GSI)的内容,请搜索钉钉群号加群进行咨询。钉钉群号:24490017825。
背景信息
分区表上传统的索引为局部索引。局部索引对于逻辑表而言也是分区的,局部索引的分区方式与表的分区方式相同。局部索引单个分区的数据由分区表单个分区的数据构建而成,且局部索引的分区与分区表的分区一一对应,所以,局部索引的索引数据只能保证在单个分区内有序,如果您想创建局部唯一索引,则索引字段必须包含全部的分区键。
当分区表上只存在局部索引时,使用分区表因受到分区键的限制,会遇到一些棘手的问题,如下:
查询条件不包含分区键时,查询数据需要扫描分区表上的所有分区,这将带来明显的读放大问题,且分区越多,读放大越严重。
查询结果对索引字段有顺序要求时,即使局部索引中每个分区的数据是有序的,也无法保证跨分区查询的索引数据全局有序,可能会触发额外的全局排序操作。
局部唯一索引必须包含全部的分区键,否则无法保证所有分区的全局唯一性约束。
PolarDB MySQL版的全局索引与局部索引相对,全局索引不分区,由全部分区的数据构建而成。所以,全局索引上的索引数据对全局的分区表有序,如果您想创建全局唯一索引,索引字段不需要包含全部的分区键。
前提条件
集群版本需为PolarDB MySQL版8.0.2版本且修订版本为8.0.2.2.7及以上。您可以通过查询版本号来确认集群版本。
使用限制
全局二级索引仅支持在InnoDB引擎上创建的分区表,不支持混合分区表。
全局二级索引不能为全文索引或空间索引。
不支持在压缩表、临时表、加密表、REDUNDANT以及COMPRESSED行格式的表上创建全局二级索引。
创建全局二级索引的列不能为分区表的主键。
创建全局二级索引的表不支持生成列(Generated Column)。
分区级别的DDL变更(新增RANGE或LIST分区除外)会导致已创建的全局二级索引失效,您需要先删除表上所有的全局二级索引,再重建二级索引,或直接使用
UPDATE GLOBAL INDEX
语法重建二级索引。
增强特性
支持使用并行DDL来并行创建全局二级索引。
支持在已创建全局二级索引的分区表上使用秒级加字段功能。
已创建全局二级索引的RANGE或LIST分区表,在新增分区时支持使用分区级别的MDL锁。
支持将已创建全局二级索引的表转换为INTERVAL RANGE分区表,同时支持在INTERVAL RANGE分区表上创建全局二级索引。
对已创建全局二级索引的分区表执行分区级别的DDL变更时,支持使用
UPDATE GLOBAL INDEX
语法重建表上的全局二级索引。示例如下:创建以
a
字段为分区键的RANGE分区表t1
,同时在b
字段上创建全局索引k1
。CREATE TABLE t1( a INT PRIMARY KEY, b INT, INDEX k1(b) GLOBAL ) PARTITION BY RANGE (`a`) (PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB);
删除
t1
表上的p1
分区并重建全局二级索引。ALTER TABLE t1 DROP PARTITION p1 UPDATE GLOBAL INDEX;
语法
创建索引时,通过在索引名称后添加LOCAL或GLOBAL关键字来指定局部索引或全局索引。
如果在创建索引时,没有指定全局二级索引,则默认创建局部索引。
示例
创建以
a
字段为分区键的分区表t1
。同时在b
字段上创建全局索引k1
。CREATE TABLE t1( a INT PRIMARY KEY, b INT, INDEX k1(b) GLOBAL ) PARTITION BY HASH(a) PARTITIONS 3;
创建以
a
字段为分区键的分区表t1
,再在t1
的b
字段上创建全局索引k1
和全局唯一索引k2
。CREATE TABLE t1( a INT PRIMARY KEY, b INT ) PARTITION BY HASH(a) PARTITIONS 3; ALTER TABLE t1 ADD INDEX k1(b) GLOBAL; CREATE UNIQUE INDEX k2 ON t1(b) GLOBAL;
性能测试
测试对象
数据量100万条,表结构和表数据相同的2张分区表。在1张分区表上创建局部索引,另外的1张分区表上创建全局二级索引。
此处以创建分区表mytest1.big_table_1
和mytest2.big_table_1
为例,其中,表mytest1.big_table_1
为创建局部索引的表,表mytest2.big_table_1
为创建全局二级索引的表。
CREATE TABLE mytest1.big_table_1(
a INT PRIMARY KEY,
b INT,
c INT,
INDEX k1(b) LOCAL
) PARTITION BY HASH(a) PARTITIONS 32;
CREATE TABLE mytest2.big_table_1(
a INT PRIMARY KEY,
b INT,
c INT,
INDEX k1(b) GLOBAL
) PARTITION BY HASH(a) PARTITIONS 32;
测试方法
针对SELECT、UPDATE和DELETE语句的查询条件中不包含分区键的场景,测试不同分区数量下,使用局部索引和全局索引的耗时。
测试结果
SELECT语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。
UPDATE语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。
DELETE语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。
由以上的测试结果可以看出:在查询条件不包含分区键的场景中,执行SELECT、UPDATE和DELETE命令时,使用全局二级索引的执行耗时较短,且数据量越大执行耗时差异越明显。