我需要一个建议:)
我有一个包含近70个表的数据库,其中许多都有超过十几个大的记录。我想把它分成几个较小的。一个用于每个大客户端数据,一个用于客户端数据的主数据库(同时还将一些数据移动到NoSQL数据库中)。由于表之间有许多复杂的关系,在复制数据之前,我正在禁用触发器,即检查外键的正确性,然后,就在提交之前我再次启用它们。
这一切都在处理少量数据,但是现在,当我试图复制一个大客户端数据时,我遇到了java堆大小/ GC内存不足的问题。
我可以增加堆大小,但这不是重点。
我正在从与客户端数据有任何关系的每个表中的某个特定id中选择数据,并将其复制到另一个数据库。这个过程如下:
我试图选择部分数据(比如选择5000行而不是全部50 000行的部分),但它在完全相同的位置失败。
在这里,我正在寻求建议,如何解决这个问题。我认为这都是因为我试图在一个大的脂肪提交中复制所有数据。原因是我必须在复制时禁用触发器,但我必须在我提交更改之前启用它们。
答案 0 :(得分:1)
当我尝试复制其中一个大客户端数据时,我遇到了java堆大小/ GC内存不足的问题。
复制数据不应该使用堆,因此您似乎不使用基于游标的查询。
参见" Getting results based on a cursor"在PostgreSQL JDBC文档中:
默认情况下,驱动程序会立即收集查询的所有结果。这对于大型数据集来说可能不方便,因此JDBC驱动程序提供了一种在数据库游标上建立ResultSet并仅获取少量行的方法。
在连接的客户端缓存少量行,当用尽时,通过重新定位光标来检索下一行行。
[...]
将代码更改为光标模式就像将Statement 的提取大小设置为适当的大小一样简单。将提取大小设置为0将导致缓存所有行(默认行为)。
因此,在代码中添加stmt.setFetchSize(1000)
(或类似的东西)将确保JDBC驱动程序不会耗尽堆。
如果您之后仍然遇到问题,那么因为您的代码保留了所有数据,这意味着它的编码错误导致复制操作。