全局二级索引(GSI)

PolarDB MySQL版支持在分区表上创建全局二级索引(Global Secondary Index,简称GSI)。使用全局二级索引可以实现透明分区表,即您可以像使用单表一样使用分区表,大大减少分区键对分区表的使用限制。

说明
  • 全局二级索引功能当前处于灰度发布阶段,如有需求,请前往配额中心,根据配额IDpolardb_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语法重建表上的全局二级索引。示例如下:

    1. 创建以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);
    2. 删除t1表上的p1分区并重建全局二级索引。

      ALTER TABLE t1 DROP PARTITION p1 UPDATE GLOBAL INDEX;

语法

创建索引时,通过在索引名称后添加LOCALGLOBAL关键字来指定局部索引或全局索引。

说明

如果在创建索引时,没有指定全局二级索引,则默认创建局部索引。

示例

  • 创建以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,再在t1b字段上创建全局索引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_1mytest2.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;

测试方法

针对SELECTUPDATEDELETE语句的查询条件中不包含分区键的场景,测试不同分区数量下,使用局部索引和全局索引的耗时。

测试结果

  • SELECT语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。image

  • UPDATE语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。image

  • DELETE语句的查询条件中不包含分区键,使用局部索引和全局索引的耗时。image

由以上的测试结果可以看出:在查询条件不包含分区键的场景中,执行SELECTUPDATEDELETE命令时,使用全局二级索引的执行耗时较短,且数据量越大执行耗时差异越明显。