如何更改和更新大型 table 以从另一个 table 添加复合键列
How to alter and update large table to add composite key columns form another table
我们的 Mysql(MariaDb) 数据库中有两个非常大的 table。 Table_1 持有多对多地图。它有一个自动递增的主键和一个两列的复合键。
Table_2指的是Table_1的主键。我们不想通过
修复这个明显的设计错误
- 在 Table_1
上使用复合主键
- 将两列添加到 Table_2
- 通过从 Table_1 复制数据来填充 Table_2 中的复合键,并在其上创建索引。
- 最好从两个 table 中删除自动递增的键列。
这些 table 有 ~300M 行,table 的大小约为 10GB 运行ge。我们需要在大约 6 小时的服务时间内完成这些更新 window。
我正在研究如何有效地执行此操作并在副本数据库上进行试验。到目前为止,我还没有尝试 运行 任何实际数据,因为普通脚本是不够的。
我不是经验丰富的数据库管理员。所以我需要一些光线来完成这项工作。
我的问题是什么是最好的 approach/tips 来有效地做到这一点?
到目前为止我尝试过的事情
我了解了新的 instant add column 功能,但我们的生产数据库使用的是 MariaDb 10.0 版,该版本较旧。
我遵循了脚本下方 this answer 和 运行 中关于具有即时添加列支持的最新数据库版本的建议(Alter table 是即时的)。 table 有大约 5000 万行(原始行的 1/6)。花了大约两个小时,这还不包括创建新索引。因此这还不够。
SET join_buffer_size = 4 * 50 * 1024 * 1024; -- 50M keys of 4 bytes each
SET optimizer_switch='mrr=on,mrr_cost_based=off,mrr_sort_keys=on,optimize_join_buffer_size=on';
SET join_cache_level = 8;
UPDATE TABLE_2
JOIN TABLE_1 ON TABLE_1_Id = TABLE_2_FKT1_Id
SET
TABLE_2_KeyPart_1 = TABLE_1_KeyPart_1,
TABLE_2_KeyPart_2 = TABLE_1_KeyPart_2
也在考虑评估这个工具
https://www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html
方案A:使用Percona的工具:pt-online-schema-change
.
方案 B:使用竞争产品:gh-ost
。
方案C:不要使用UPDATE
,那是杀手。相反,以直接的方式重建 table(s),然后使用 RENAME TABLE
将新版本交换到位。
分区不太可能有任何帮助。 Daniel 的 link 有助于完成冗长的 UPDATE
,但需要权衡时间(需要更长的时间)与侵入性(这不是问题,因为您需要维护 window)。
C 计划的更多细节(我更喜欢这个 案例):
CREATE TABLE(s) ... -- with new names, and all the new features except secondary indexes
INSERT INTO new SELECT ... FROM old table(s)
RENAME TABLE real1 TO old1,
new1 TO real1,
real2 TO old2,
new2 TO real2;
test -- you still undo the RENAME if necessary
DROP TABLE old1, old2;
我们的 Mysql(MariaDb) 数据库中有两个非常大的 table。 Table_1 持有多对多地图。它有一个自动递增的主键和一个两列的复合键。 Table_2指的是Table_1的主键。我们不想通过
修复这个明显的设计错误- 在 Table_1 上使用复合主键
- 将两列添加到 Table_2
- 通过从 Table_1 复制数据来填充 Table_2 中的复合键,并在其上创建索引。
- 最好从两个 table 中删除自动递增的键列。
这些 table 有 ~300M 行,table 的大小约为 10GB 运行ge。我们需要在大约 6 小时的服务时间内完成这些更新 window。 我正在研究如何有效地执行此操作并在副本数据库上进行试验。到目前为止,我还没有尝试 运行 任何实际数据,因为普通脚本是不够的。 我不是经验丰富的数据库管理员。所以我需要一些光线来完成这项工作。 我的问题是什么是最好的 approach/tips 来有效地做到这一点?
到目前为止我尝试过的事情
我了解了新的 instant add column 功能,但我们的生产数据库使用的是 MariaDb 10.0 版,该版本较旧。
我遵循了脚本下方 this answer 和 运行 中关于具有即时添加列支持的最新数据库版本的建议(Alter table 是即时的)。 table 有大约 5000 万行(原始行的 1/6)。花了大约两个小时,这还不包括创建新索引。因此这还不够。
SET join_buffer_size = 4 * 50 * 1024 * 1024; -- 50M keys of 4 bytes each
SET optimizer_switch='mrr=on,mrr_cost_based=off,mrr_sort_keys=on,optimize_join_buffer_size=on';
SET join_cache_level = 8;
UPDATE TABLE_2
JOIN TABLE_1 ON TABLE_1_Id = TABLE_2_FKT1_Id
SET
TABLE_2_KeyPart_1 = TABLE_1_KeyPart_1,
TABLE_2_KeyPart_2 = TABLE_1_KeyPart_2
也在考虑评估这个工具 https://www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html
方案A:使用Percona的工具:pt-online-schema-change
.
方案 B:使用竞争产品:gh-ost
。
方案C:不要使用UPDATE
,那是杀手。相反,以直接的方式重建 table(s),然后使用 RENAME TABLE
将新版本交换到位。
分区不太可能有任何帮助。 Daniel 的 link 有助于完成冗长的 UPDATE
,但需要权衡时间(需要更长的时间)与侵入性(这不是问题,因为您需要维护 window)。
C 计划的更多细节(我更喜欢这个 案例):
CREATE TABLE(s) ... -- with new names, and all the new features except secondary indexes
INSERT INTO new SELECT ... FROM old table(s)
RENAME TABLE real1 TO old1,
new1 TO real1,
real2 TO old2,
new2 TO real2;
test -- you still undo the RENAME if necessary
DROP TABLE old1, old2;