【发布时间】:2010-09-11 20:27:58
【问题描述】:
我在 PostgresQL 中有一个非常大的数据库表和一个类似“已复制”的列。每一个新行开始时都是未复制的,稍后将被后台程序复制到另一个东西上。该表“btree(ID) WHERE replicated=0”上有一个部分索引。后台程序最多选择 2000 个条目(LIMIT 2000),对它们进行处理,然后使用 2000 个准备好的 sql 命令在一个事务中提交更改。
现在的问题是我想给用户一个选项来重置这个复制值,让它再次全部为零。
一个更新表集replicated=0;
不可能:
- 需要很长时间
- 由于 MVCC,它复制了表格的大小
- 在一个事务中完成:要么失败,要么通过。
在这种情况下,我实际上不需要事务功能:如果系统出现故障,它将只处理其中的一部分。
其他几个问题: 做一个
update set replicated=0 where id >10000 and id<20000
也很糟糕:它对整个表进行顺序扫描,这太慢了。 如果不这样做,它仍然会很慢,因为它会进行太多的搜索。
我真正需要的是一种遍历所有行、更改它们而不被绑定到巨大事务的方法。
奇怪的是
UPDATE table
SET replicated=0
WHERE ID in (SELECT id from table WHERE replicated= LIMIT 10000)
也很慢,虽然这应该是件好事:按 DISK-order 遍历表...
(请注意,在这种情况下,还有一个索引涵盖了这一点)
(Mysql 之类的更新 LIMIT 不适用于 PostgresQL)
顺便说一句:真正的问题更复杂,我们在这里讨论的是已经部署的嵌入式系统,因此远程架构更改很困难,但可能 不幸的是,它是 PostgresQL 7.4。
我所说的行数是例如90000000。数据库的大小可以是几十G。
数据库本身只包含5张表,其中一张非常大。 但这不是一个糟糕的设计,因为这些嵌入式盒子只与一种实体一起操作,而不是 ERP 系统或类似的东西!
有什么想法吗?
【问题讨论】:
标签: sql database postgresql sql-update mvcc