使用 Ruby on Rails 迁移将大型 PostgreSQL 表复制到新表的更快方法

Faster way to copy a large PostgreSQL table into a new table with Ruby on Rails migrations

提问人:bahri 提问时间:9/8/2023 最后编辑:bahri 更新时间:9/8/2023 访问量:115

问:

我正在用 PostgreSQL 数据库做一个 Ruby on Rails 项目,我有一个包含数百万条记录的大表。我想将此表复制到另一个名为 new_X 的表中。我希望两个表在最后是相同的。我的意思是,相同的约束和默认值。此外,旧表中的主键是 (id)。我希望new_X具有相同的自动递增主键。 我有两种方法;

方法 1:复制表,然后添加约束和索引

首先将值复制到新表中,为 id 创建一个序列,然后添加非 null 约束和默认值。

# Copy the old table to new table
execute <<-SQL.squish
  CREATE TABLE new_X AS TABLE old_X;
SQL

# Create a new serial sequence for id
execute <<-SQL.squish
  CREATE SEQUENCE new_X_id_seq;
SQL

# Update the id column to use the new sequence
execute <<-SQL.squish
  ALTER TABLE new_X
  ALTER COLUMN id SET DEFAULT nextval('new_X_id_seq');
SQL

# Set the sequences current value to the maximum existing id value
execute <<-SQL.squish
  SELECT setval('new_X_id_seq', (SELECT max(id) FROM new_X));
SQL

# Set the id column as the primary key
execute <<-SQL.squish
  ALTER TABLE new_X
  ADD PRIMARY KEY (id);
SQL

创建表并添加记录后,现在我将添加约束、默认值和索引。例如,我必须添加这个 not null 约束。还有索引。

# Add the created_at and updated_at columns with NOT NULL constraint
execute <<-SQL.squish
  ALTER TABLE new_X
  ADD COLUMN created_at timestamp without time zone NOT NULL DEFAULT NOW(),
  ADD COLUMN updated_at timestamp without time zone NOT NULL DEFAULT NOW();
SQL

现在添加索引。

# Add index for is_Y
execute <<-SQL.squish      
CREATE INDEX CONCURRENTLY index_new_X_on_is_Y
  ON new_X (is_Y);
SQL

创建包含列名、约束、默认值、索引的表,然后插入数据

创建名称为 new_X 的表。包含所有列名、约束、默认值、索引。创建后,从旧表中插入数百万条记录。

我想我更接近接近 #1,但我希望社区在处理类似场景时提供任何见解、最佳实践或经验。谢谢!

由于我的开发环境中没有数百万条记录,因此我无法测试这些行为。

ruby-on-rails postgresql 数据库迁移 rails-migrations

评论

1赞 engineersmnky 9/8/2023
以下方法可能适合您。您可以使用复制所有列名、约束、默认值、索引。然后插入所有数据。这将使约束、索引、标识序列等保持完整,并应按原样移动所有现有数据。CREATE TABLE new_X (LIKE old_x INCLUDING ALL)INSERT INTO new_x OVERRIDING SYSTEM VALUE SELECT * FROM old_x
1赞 mechnicov 9/8/2023
@engineersmnky看起来 FK 约束不包含在INCLUDING ALL
0赞 bahri 9/8/2023
@engineersmnky 感谢您的回答!它在我的开发数据库中起作用。CREATE TABLE new_X AS TABLE old_X之间是否有任何性能差异;你的建议是什么?我想进一步调查外键。你能给我一份文件或一些关于这个的链接吗?
2赞 Les Nightingill 9/8/2023
您提到您无法在开发数据库中对此进行测试。如果不先在开发中对其进行测试,我绝对不会在生产中这样做。我建议转储您的生产数据库并将数据加载到您的开发环境中。如果我认为存在与数据相关的生产问题,或者测试性能调整,我会定期这样做。
0赞 Milind 9/9/2023
这有帮助吗 - stackoverflow.com/questions/68098793/... ????

答: 暂无答案