2015-11-03 99 views
7

我有一个相当大的表(大约10亿行),我需要将ID类型从SERIAL更新为BIGSERIAL;猜猜为什么?:)。postgreSQL同时将列类型从int更改为bigint

基本上这可能是与这个命令来完成:

execute "ALTER TABLE my_table ALTER COLUMN id SET DATA TYPE bigint" 

然而,将永远锁住我的桌子,把我的网络服务了。

是否有一个相当简单的方法同时进行此操作(无论它将花费多少时间)?

回答

3

如果没有外键指向您的ID,你可以到旧添加新柱,填充它,放下旧的和新的命名:

alter table my_table add column new_id bigint; 

begin; update my_table set new_id = id where id between 0 and 100000; commit; 
begin; update my_table set new_id = id where id between 100001 and 200000; commit; 
begin; update my_table set new_id = id where id between 200001 and 300000; commit; 
begin; update my_table set new_id = id where id between 300001 and 400000; commit; 
... 

create unique index my_table_pk_idx on my_table(new_id); 

begin; 
alter table my_table drop constraint my_table_pk; 
alter table my_table alter column new_id set default nextval('my_table_id_seq'::regclass); 
update my_table set new_id = id where new_id is null; 
alter table my_table add constraint my_table_pk primary key using index my_table_pk_idx; 
alter table my_table drop column id; 
alter table my_table rename column new_id to id; 
commit; 
+0

谢谢,这个解决方案是非常优雅。在我看来,仍然存在问题。当我们填充new_id列时,新行将被插入到表中,new_id值将不会被设置,唯一索引创建可能会失败。 我们可以在插入过程中添加触发器设置new_id,直到我们在其上添加nexval默认值为止? –

+0

唯一索引忽略'null'值,因此不需要触发。 –

+0

如果'alter table my_table add column new_id bigint;'需要很长时间(需要超过1小时但尚未完成)并阻止其他读取操作? –

相关问题