创建和管理读取副本上的索引

本页面介绍如何在 Cloud SQL 读取副本上添加和删除索引。虽然副本通常为只读,但有时您可能需要为表创建二级索引以用于报告。Cloud SQL 提供了一组用于管理这些索引的存储过程。

术语

  • 聚簇索引。MySQL 表上的主索引,用于对磁盘上的行进行物理排序。当您在表上定义主键时,MySQL 会将其用作聚簇索引。一个表上只能有一个聚簇索引。
  • 二级索引。MySQL 表上的额外索引,可优化查询性能。

索引的存储过程

Cloud SQL 在 mysql 架构中包含了两个存储过程,您可以使用它们在 MySQL 读取副本上添加和删除二级索引。请注意,尽管这些过程可以在主源实例上运行,但它们是为读取副本设计的。

mysql.addSecondaryIdxOnReplica
在数据库上添加二级索引。此存储过程是 CREATE INDEX DDL 语句的封装容器。

参数:

  • idxType - 要创建的索引类型。例如,传递 UNIQUE 以创建唯一索引。
  • idxName - 索引的名称。
  • tableName - 表的名称,格式为 schema.name。
  • idxDefinition - 索引的定义。不要用括号括起。
  • idxOption - 创建索引时要传递的其他选项。例如,在 MySQL 8.0 中,对于不可见索引,一个选项可以传递 INVISIBLE。

语法:

mysql.addSecondaryIdxOnReplica(idxType, idxName, tableName, idxDefinition, idxOption)
     
mysql.dropSecondaryIdxOnReplica
删除数据库上的二级索引。此存储过程是 DROP INDEX DDL 语句的封装容器。

参数:

  • idxName - 索引的名称。
  • tableName - 表的名称,格式为 schema.name。
  • idxOption - 删除索引时要传递的其他选项。例如 INPLACE 这样的算法选项。

语法:

mysql.dropSecondaryIdxOnReplica(idxName, tableName, idxOption)
      

对于 idxTypeidxOption 参数,请参阅 Cloud SQL 实例上运行的 MySQL 主要版本的文档。

示例

正确用法

以下是这些过程的一些示例调用。假设我们有一个具有以下定义的表。

CREATE TABLE sampletest.t1(
   id int(10) unsigned NOT NULL AUTO_INCREMENT,
   first_name varchar(64) NOT NULL,
   last_name varchar(64) NOT NULL,
   license_id int NOT NULL,
   PRIMARY KEY (id),
   KEY idx_fname (first_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

如果要在 first_namelast_name 列上创建一个名为 t1_fname_lname 的常规索引,则执行以下调用:

call mysql.addSecondaryIdxOnReplica('', 't1_fname_lname', 'sampletest.t1', 'first_name, last_name', '')

如果您还想在 license_id 列上创建一个名为 t1_license_id 且具有注释“unique licenses id”的唯一索引,则执行以下调用:

call mysql.addSecondaryIdxOnReplica('unique', 't1_license_id', 'sampletest.t1', 'license_id', 'comment \"unique license id\"')

如果随后想要删除 t1_fname_lname 索引,则执行以下调用:

call mysql.dropSecondaryIdxOnReplica('t1_fname_lname', 'sampletest.t1', '')

错误用法

由于 idxDefinition 参数被括号括起,以下在 first_namelast_name 列上创建索引的尝试将失败。

call mysql.addSecondaryIdxOnReplica('', 't1_extra_parenthesis', 'sampletest.t1', '(first_name, last_name)', '')

您只能在客户创建的表上添加索引。以下在 mysql.servers 表的主机列上创建索引的尝试将失败。

call mysql.addSecondaryIdxOnReplica('', 'idx_invalid', 'mysql.servers', 'host', '')

您只能使用 dropSecondaryIdxOnReplica 过程删除之前使用 addSecondaryIdxOnReplica 过程创建的索引。例如,以下删除现有 idx_fname 索引的调用会失败。

call mysql.dropSecondaryIdxOnReplica('idx_fname', 'sampletest.t1', '')

在这些过程调用中,SQL 注入将失败。例如,以下包含注释序列的 SQL 注入将失败。

call mysql.addSecondaryIdxOnReplica(\"user 'a'@'%' --\", 'idx_fname', 'sampletest.t1', 'first_name', '')

同样,以下包含分隔符的 SQL 注入尝试将失败。

call mysql.addSecondaryIdxOnReplica('', 'idx_fname', 'sampletest.t1', 'first_name', ';flush status')

重新创建读取副本

有时在出现问题时,Cloud SQL 会从主源实例重新创建读取副本,以便快速恢复实例。重新创建操作之前在读取副本上创建的索引将不会保留。客户需要负责在读取副本上使用存储过程重新创建这些索引。

后续步骤