2010-06-04 312 views
9

我想将一些数据从一个表移动到另一个表(可能具有不同的模式)。即进入头脑简单的解决办法是 -将数据从一个表移动到另一个表,postgresql版

start a transaction with serializable isolation level; 
INSERT INTO dest_table SELECT data FROM orig_table,other-tables WHERE <condition>; 
DELETE FROM orig_table USING other-tables WHERE <condition>; 
COMMIT; 

现在,如果数据量是相当大的,而且<condition>是计算昂贵?在PostgreSQL中,可以使用RULE或存储过程来即时删除数据,只评估一次条件。哪种解决方案更好?还有其他选择吗?

回答

0

您可能会在表中的数据转储到一个文件,然后将其插入到使用COPY 通常COPYINSERT更快的另一个表。

+1

我做了一些测试处理使用触发器的大量数据,逐行,以及使用单个事务的存储过程。 存储过程方法更快。 – pcent 2010-06-04 12:45:49

+0

您还应该优化您的PostgreSQL服务器以提高性能。阅读: http://wiki.postgresql.org/wiki/Performance_Optimization – pcent 2010-06-04 12:48:23

+0

嗯,我认为指南应该有资格说,一个COPY比一组INSERT语句更快,每行一个。 INSERT ... SELECT用于复制数据我认为是最优的,因为数据没有被传递到执行程序之外。 – araqnid 2010-06-04 13:12:22

7

如果条件太复杂以至于你不想执行两次(对我来说这听起来不太可能,但无论如何),一种可能性是在原表上的ALTER TABLE ... ADD COLUMN添加一个布尔字段,并运行表上的UPDATE将该字段设置为true WHERE <condition>。然后,您的INSERTDELETE命令可以简单地检查此列中的WHERE子句。

不要忘记随后从源表和目标表中删除列!嗯,即使更少侵入性的是创建一个新的临时表,其唯一目的是包含您想包含记录的PK。首先将INSERT这个表格“定义”要操作的一组行,然后加入这张表中以复制表格INSERTDELETE。这些连接将会很快,因为表格PK被编入索引。


[编辑] 斯科特·贝利在评论中建议显然是做到这一点的正确方法,希望我能想到这一点我自己!假设所有原始表的PK字段将出现在目标表中,则不需要临时表 - 只需使用复杂的WHERE条件将原始表插入到目标表中,然后通过加入此表即可将DELETE从原始表中插入。我觉得现在提出一个单独的桌子很愚蠢! :)

+0

临时表得到我的投票。更新行然后删除它们意味着在堆中创建大量垃圾,并且需要触摸表格模式(不是那真的很重要) – araqnid 2010-06-04 13:15:23

+0

+1用于PK的临时表。 – rfusca 2010-06-04 13:34:21

+4

您不需要临时表或执行两次昂贵的计算。在插入新表格时执行一次计算。然后从旧表中删除记录位于新表中的旧表。 – 2010-06-04 23:16:13

24

[扩展在dvv's answer]

您可以移动到现有的表如下。对于不匹配的模式,您应该指定列。

WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
INSERT INTO <existing_table> --specify columns if necessary 
SELECT [DISTINCT] * FROM moved_rows; 

但是想要将数据移动到表(不是现有的),外语法是不同的:

CREATE TABLE <new_table> AS 
WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
SELECT [DISTINCT] * FROM moved_rows; 
相关问题