AWS RDS下MySQL ADD COLUMN慢

Posted

技术标签:

【中文标题】AWS RDS下MySQL ADD COLUMN慢【英文标题】:MySQL ADD COLUMN slow under AWS RDS 【发布时间】:2021-10-20 16:10:56 【问题描述】:

我有一个具有以下设置的 RDS mysql

类:db.m5.xlarge 存储:预置 1000 IOPS (SSD)

然后我想在一个大小约为 20 GB 的表中添加几列(根据INFORMATION_SCHEMA.files)。这是我的声明:

ALTER TABLE MY_TABLE
ADD COLUMN NEW_COLUMN_1 DECIMAL(39, 30) NULL,
ADD COLUMN NEW_COLUMN_2  DECIMAL(39, 30) NULL,
ADD COLUMN NEW_COLUMN_3 INT(10) UNSIGNED NULL,
ADD CONSTRAINT SOME_CONSTRAINT FOREIGN KEY (NEW_COLUMN_3) REFERENCES SOME_OTHER_TABLE(SOME_OTHER_PK),
ADD COLUMN NEW_COLUMN_4 DATE NULL;

此查询需要 172 分钟才能执行。大部分时间都花在将数据处理到临时表上。

在该操作期间,没有执行其他查询(读取或写入)。我只有自己的数据库。 SHOW FULL PROCESSLISTState 等于 copy to tmp table 我的查询。

我不明白的是,AWS RDS 控制台告诉我写入吞吐量在 30 MB/s 和 35 MB/s 之间持续了 172 分钟。

假设写入吞吐量为 30 MB/s,我应该能够写入 30 * 60 * 172 = 309600 MB = 302 GB。这比操作期间创建的临时表的大小 (20 GB) 大得多。

那么两个问题:

    mysql/rds 在我的临时表旁边写了什么?有没有办法禁用它,以便我可以获得创建临时表的全部带宽? 有什么方法可以加速该操作吗?写入 20 GB 数据需要 3 小时似乎相当长。

【问题讨论】:

最好在dba.stackexchange.com提出这个问题 【参考方案1】:

我使用的是 MySQL 5.7。根据MySQL blog post,8.0 版改进了这种情况:“InnoDB 现在支持 Instant ADD COLUMN”。

因此,我更改了查询以使用新功能。

-- Completes in 0.375 seconds!
ALTER TABLE MY_TABLE
ADD COLUMN NEW_COLUMN_1 DECIMAL(39, 30) NULL,
ADD COLUMN NEW_COLUMN_2  DECIMAL(39, 30) NULL,
ADD COLUMN NEW_COLUMN_3 INT(10) UNSIGNED NULL,
-- 'ALGORITHM=INSTANT' is not compatible with foreign keys. 
-- The foreign key will need to be added in another statement
-- ADD CONSTRAINT SOME_CONSTRAINT FOREIGN KEY (NEW_COLUMN_3) REFERENCES SOME_OTHER_TABLE(SOME_OTHER_PK),
ADD COLUMN NEW_COLUMN_4 DATE NULL, 
-- the new option
ALGORITHM=INSTANT;

-- This completed in about 6 minutes. 
-- Adding the foreign creates an index under the hood. 
-- This index was 1.5 GB big.
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE MY_TABLE
  ADD FOREIGN KEY (NEW_COLUMN_3) REFERENCES SOME_OTHER_TABLE(SOME_OTHER_PK);
SET FOREIGN_KEY_CHECKS=1;

所以我的结论:

如果可以的话,升级到 MySQL 8 确保始终使用(如果可能)ALGORITHM=INSTANT 选项。

【讨论】:

【参考方案2】:

InnoDB 可能是您正在使用的存储引擎,因为它是默认存储引擎。 InnoDB 会执行一些看似多余的 I/O,以确保没有数据丢失。

例如:

在缓冲池中修改的数据和索引页必须写入表空间。在添加列的过程中,表格可能需要拆分一些页面,因为行变得更宽,每页容纳的行更少。 在将页面写入表空间期间,InnoDB 首先将这些页面写入双写缓冲区,以确保在页面写入期间发生崩溃时不会丢失数据。 事务被写入 InnoDB 重做日志,这甚至可能导致多次覆盖日志中的同一块。 如果为复制目的而启用,事务也会写入二进制日志。尽管在 ALTER TABLE 语句的转换中这不应该是一个很大的成本,因为 DDL 语句总是以语句格式而不是行格式写入二进制日志。

您还询问了如何加快 ALTER TABLE 的速度。希望它运行得更快的原因通常是因为在 ALTER TABLE 期间,表被锁定并且可能会阻塞并发查询。

在我的公司,我们使用免费工具pt-online-schema-change,因此我们可以在更改表格时或多或少地继续使用表格。以这种方式完成更改实际上需要更长的时间,但它并没有那么不方便,因为它不会阻止我们对表的访问。

【讨论】:

以上是关于AWS RDS下MySQL ADD COLUMN慢的主要内容,如果未能解决你的问题,请参考以下文章

AWS RDS 大型实例上的 MySQL 全文搜索速度极慢

AWS RDS DB 部署时速度慢

使用 AWS RDS 的 Django `TransactionTestCase` 测试用例非常慢

使用 Terraform 创建 AWS MySQL RDS 实例时出错

更改 AWS RDS mysql时区 -摘自网络

如何连接mysql数据库(AWS下的RDS实例)