在PostgreSQL中将数据从表移动到另一个

时间:2018-10-16 06:18:52

标签: sql postgresql

我的数据库中有2个表。它们都有超过16m的记录,它们具有相同的uuid关系(我对两个uuid字段都有索引)。其中一个约为166GB,另一个约为50GB。我将在问题上更改表名称,但希望您能解决问题。

比方说,我的第一个表称为用户,第二个表是个人资料。 现在,我的用户表上有一个字段,我想将其复制到个人资料表中。

昨晚我做了一些事情,但仍在处理中,已经超过10个小时了。

我现在有3个问题。第一个问题;我的查询可以吗?

ALTER TABLE profiles ADD COLUMN start_stamp TIMESTAMP DEFAULT NOW();
SET start_stamp = (SELECT start_stamp::DATE FROM users WHERE uuid = profiles.uuid);
CREATE INDEX start_stamp ON profiles;

第二个问题;这两个查询之间有什么区别?如果可以,有什么区别,哪个更好?

UPDATE profiles 
SET start_stamp = (SELECT start_stamp::DATE FROM users WHERE uuid = profiles.uuid);

QUERY PLAN
--------------------------------------------------------------------------
Update on profiles  (cost=0.00..159956638.61 rows=18491638 width=116)
->  Seq Scan on profiles  (cost=0.00..159956638.61 rows=18491638 width=116)
     SubPlan 1
       ->  Index Scan using unique_user_uuid on users  (cost=0.56..8.58 rows=1 width=20)
             Index Cond: ((uuid)::text = (profiles.uuid)::text)




UPDATE profile
SET start_stamp = users.start_stamp
FROM users
WHERE profiles.start_stamp = users.start_stamp;

QUERY PLAN
--------------------------------------------------------------------------
Update on profiles  (cost=2766854.25..5282948.42 rows=11913522 width=142)
->  Hash Join  (cost=2766854.25..5282948.42 rows=11913522 width=142)
     Hash Cond: ((profiles.uuid)::text = (users.uuid)::text)
     ->  Seq Scan on profiles  (cost=0.00..1205927.56 rows=18491656 width=116)
     ->  Hash  (cost=2489957.22..2489957.22 rows=11913522 width=63)
           ->  Seq Scan on users  (cost=0.00..2489957.22 rows=11913522 width=63)

我的最后一个问题是;有没有更好的方法将值从一个表复制到具有16m和200gb记录的另一个表?

谢谢。

2 个答案:

答案 0 :(得分:1)

更新/复制大量数据的最快方法是CTAS(选择创建表)。只有在您有权这样做并且可以更改名称或删除原始表的情况下,才有可能。

您的情况是这样的:

create table tmp_profiles as
select p.* , us.strat_stamp:date
 from profiles p
 left join users u on p.uuid = us.uuid;

drop table profiles;

alter table tmp_profiles, rename to profiles;

之后,您必须重新创建键,索引和其他约束。

如果您更新表中超过5%的记录,则CTAS将比常规更新至少快几倍。低于该阈值更新可能比CTAS更快。

答案 1 :(得分:0)

您的两个查询都相同。 这将永远需要更新。这是一个众所周知的问题,将NOT NULL COLUMN添加到更大的表中

解决方案1:分批更新默认值,运行多个查询以更新日期 Sol2:重新创建整个表

有用的链接,用于Postgres中的大量行: https://medium.com/doctolib-engineering/adding-a-not-null-constraint-on-pg-faster-with-minimal-locking-38b2c00c4d1c

https://dba.stackexchange.com/questions/52517/best-way-to-populate-a-new-column-in-a-large-table/52531#52531

https://dba.stackexchange.com/questions/41059/optimizing-bulk-update-performance-in-postgresql