提问人:bahri 提问时间:9/8/2023 最后编辑:bahri 更新时间:9/8/2023 访问量:115
使用 Ruby on Rails 迁移将大型 PostgreSQL 表复制到新表的更快方法
Faster way to copy a large PostgreSQL table into a new table with Ruby on Rails migrations
问:
我正在用 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,但我希望社区在处理类似场景时提供任何见解、最佳实践或经验。谢谢!
由于我的开发环境中没有数百万条记录,因此我无法测试这些行为。
答: 暂无答案
评论
CREATE TABLE new_X (LIKE old_x INCLUDING ALL)
INSERT INTO new_x OVERRIDING SYSTEM VALUE SELECT * FROM old_x
INCLUDING ALL