本页面介绍如何在 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)
对于 idxType
和 idxOption
参数,请参阅 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_name
和 last_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_name
和 last_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 会从主源实例重新创建读取副本,以便快速恢复实例。重新创建操作之前在读取副本上创建的索引将不会保留。客户需要负责在读取副本上使用存储过程重新创建这些索引。