我必须将值从一个表复制到另一个表(相同的表方案)。什么更好(性能):
- 删除 table1 并创建为 select * from table2
- 删除表 1 中的所有行并插入表 2 中的所有行
更新: 我在几乎有 3k 行的表上做了一个小测试。 删除和创建大约需要 60 毫秒,而删除和插入大约需要 30 毫秒。
最佳答案
我看到四种有用的方法来替换表格的内容。它们都不是“显然正确的”,但这取决于您的要求。
(在单个事务中)
DELETE FROM foo;插入 foo 选择 ...
Pro:最佳并发性:不会锁定访问该表的其他事务,因为它利用了 Postgres 的 MVCC。
缺点:如果单独测量插入速度,可能是最慢的。导致 autovacuum 清理死行,从而产生更高的 I/O 负载。
TRUNCATE foo;插入 foo 选择 ...
Pro:对于较小的表格最快。导致比#1 更少的写 I/O
缺点:排除所有其他读取器——从表中读取的其他事务将不得不等待。
TRUNCATE foo
,删除表上的所有索引,INSERT INTO foo SELECT ...
,重新创建所有索引。专业版:对于大型表最快,因为使用
CREATE INDEX
创建索引比增量更新它们更快。缺点:与 #2 相同
切换器。创建两个相同的表
foo
和foo_tmp
TRUNCATE foo_tmp; INSERT INTO foo_tmp SELECT ...; ALTER TABLE foo RENAME TO foo_tmp1; ALTER TABLE foo_tmp RENAME TO foo; ALTER TABLE foo_tmp1 RENAME TO foo_tmp;
感谢 PostgreSQL 的事务性 DDL 功能,如果这是在事务中完成的,则重命名会在其他事务不注意的情况下执行。您还可以将其与 #3 结合使用并删除/创建索引。
优点:执行的 I/O 较少,如 #2,并且不会锁定其他读取器(仅在重命名部分进行锁定)。
缺点:最复杂。此外,您不能让外键或 View 指向该表,因为它们在重命名后会指向错误的表。
关于performance - PostgreSQL 中的 DROP 和 CREATE 与 DELETE 和 INSERT 对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7022519/