2012-12-14 37 views
1

我需要更新表中的成千上万行。例如,我有1000行的ID - 1,2 .. 1000:如何更新PostgreSQL中的大量行?

mytable: 
| id | value1 | value2 | 
| 1 | Null | Null | 
| 2 | Null | Null | 
... 
| 1000 | Null | Null | 

现在我需要更改前10行。我能做到这一点是这样的:

UPDATE mytable SET value1=42, value2=111 WHERE id=1 
... 
UPDATE mytable SET value1=42, value2=111 WHERE id=10 

这需要很多的要求,而不是非常快,所以我决定做这个优化:

UPDATE mytable SET value1=42 WHERE id in (1, 2, 3.. 10) 
UPDATE mytable SET value2=111 WHERE id in (1, 2, 3.. 10) 

注意:在这种情况下,我其实可以写SET value1=42, value2=111,但在现实世界的应用程序中,这组ids不同,对于其中一行,我需要设置value1,对于其他 - value2,我需要设置两行的某些子集。因为这个我需要两个查询。

问题是我有非常大量的id。这个查询是关于1Mb的东西!

Q1:这是一个正确的方式来优化此更新?

Q2:发送这么大的查询是否正确?我可以通过将此查询分成几个较小的部分来获得更快的更新吗?

我不能使用where声明,我只是在我的程序中有很多行ID。

回答

2

创建一个TEMPORARY TABLE并用您的目标ID和新值填充它。然后使用UPDATE with FROM子句加入到该目标中,并使用单个命令完成。

一般来说,只要你有大量的id/values这样的生活,如果你先将它们移动到数据库中,它们会变得更容易。

1

Q1:这是一个正确的方式来优化此更新?

应该仍然可以使用CASE ... WHEN语法结构把它写在一个单一的查询:

UPDATE mytable SET 
    value1 = 
    CASE 
     WHEN id IN (1, 2, 3, 10) THEN 42 
     WHEN id IN (11,12,13, 20) THEN 43 
     ELSE value1 
    END, 
    value2 =  
    CASE 
     WHEN id IN (1, 2, 3, 10) THEN 42 
     WHEN id IN (11,12,13, 20) THEN 43 
     ELSE value2 
    END; 

你提到,你可能必须更新多点行,而上面让你在单个查询中没有问题的情况下做到这一点。

更新:我忽略了速度是您主要关心的事实(您说“优化”),我的回答在这方面是不正确的。按照所选答案中的解释使用临时表可以获得更好的性能。

Q2:那么,是否可以发送查询是如此之大?我可以通过将此查询分成几个较小的部分来获得更快的更新吗?

我不认为PostgreSQL的有太大问题处理大量的查询(超过1MB甚至更大)。请记住,SQL DB初始化脚本可以比1mb大得多。

+0

这个查询在我的情况下工作10个小时,但有很多小的更新的天真方法 - 原始的生,使工作在一个半小时内完成。 – Lazin

+0

感谢您花时间对其进行测试:很明显,临时表方法在这种情况下是最快的。 – didierc