java - 将数据库拆分为较小的数据库。单次提交数据过多

标签 java postgresql hibernate

我需要建议:)

我有一个包含近 70 个表的数据库,其中许多表都有超过一千万条大记录。我想把它分成几个更小的。一个用于每个大客户数据,一个主数据库用于存储其余客户的数据(同时还将部分数据移至 NoSQL 数据库)。由于表之间有许多复杂的关系,在复制数据之前,我禁用了触发器,用于检查外键的正确性,然后在提交之前再次启用它们。

这一切都在处理少量数据,但现在,当我尝试复制其中一个大客户端数据时,我遇到了 java 堆大小/GC 内存不足的问题。

我可以增加堆大小,但这不是重点。

我通过某个特定 ID 从与客户端数据有任何关系的每个表中选择数据,并将其复制到另一个数据库。该过程如下所示:

  1. 从表格中选择数据
  2. 将数据插入另一个数据库
  3. 复制序列(正在复制的数据的 max(id))
  4. 齐平/透明
  5. 对包含客户数据的每个表重复此操作

我试图选择部分数据(例如选择具有 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/

相关文章:

java - Hibernate 是更新而不是插入,为什么?

php - 如何在我的mysql数据库中获取planet-latest.osm.bz2?

PostgreSQL 9.3 : missing FROM-clause entry for table

java.lang.ClassNotFoundException : javax. 持久性.EntityManagerFactory

java - Android:总是在 Intent 中传递的额外内容中接收空对象

sql - 如何展平 PostgreSQL 结果

java - 通过嵌套列表对象中的多个值查找对象 Hibernate、Jpa

java - Joda 日期时间转换区域设置

java - int 的基本算术运算 - Java

java - ClassLoader问题导致ClassCastException的解决方法