我需要建议:)
我有一个包含近 70 个表的数据库,其中许多表都有超过一千万条大记录。我想把它分成几个更小的。一个用于每个大客户数据,一个主数据库用于存储其余客户的数据(同时还将部分数据移至 NoSQL 数据库)。由于表之间有许多复杂的关系,在复制数据之前,我禁用了触发器,用于检查外键的正确性,然后在提交之前再次启用它们。
这一切都在处理少量数据,但现在,当我尝试复制其中一个大客户端数据时,我遇到了 java 堆大小/GC 内存不足的问题。
我可以增加堆大小,但这不是重点。
我通过某个特定 ID 从与客户端数据有任何关系的每个表中选择数据,并将其复制到另一个数据库。该过程如下所示:
- 从表格中选择数据
- 将数据插入另一个数据库
- 复制序列(正在复制的数据的 max(id))
- 齐平/透明
- 对包含客户数据的每个表重复此操作
我试图选择部分数据(例如选择具有 5000 行的部分,而不是全部 50 000 行),但它在完全相同的位置失败。
我在这里寻求建议,如何解决这个问题。我认为这都是因为我试图将所有数据复制到一个大的脂肪提交中。其原因是我必须在复制时禁用触发器,但也必须在提交更改之前启用它们。
最佳答案
When I'm trying to copy one of the big client data I have a problem with the java heap size/GC out of memory.
复制数据不应使用堆,因此您似乎没有使用基于游标的查询。
请参阅 PostgreSQL JDBC 文档中的“Getting results based on a cursor ”:
By default the driver collects all the results for the query at once. This can be inconvenient for large data sets so the JDBC driver provides a means of basing a ResultSet on a database cursor and only fetching a small number of rows.
A small number of rows are cached on the client side of the connection and when exhausted the next block of rows is retrieved by repositioning the cursor.
[...]
Changing code to cursor mode is as simple as setting the fetch size of the Statement to the appropriate size. Setting the fetch size back to 0 will cause all rows to be cached (the default behaviour).
因此,在代码中添加 stmt.setFetchSize(1000)
(或类似的内容) 将确保 JDBC 驱动程序不会耗尽堆。 p>
如果此后您仍然遇到问题,那么这是因为您的代码保留了所有数据,这意味着复制操作的编码错误。
关于java - 将数据库拆分为较小的数据库。单次提交数据过多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45424675/