JOOQ 插入到具有大量记录的选择中

Posted

技术标签:

【中文标题】JOOQ 插入到具有大量记录的选择中【英文标题】:JOOQ Insert into select with large number of records 【发布时间】:2021-11-06 09:15:57 【问题描述】:

我正在尝试通过从不同的表中进行选择来插入大量记录。

在下面的示例中,BAR 表有大约 100 万条记录,并试图将所有这些记录插入 FOO 表中。有没有一种方法可以在不使用加载器 API 或使用 JOOQ 批量插入的情况下有效地做到这一点?

仅供参考,我试图避免将所有记录加载到内存中的方法,所以我没有使用需要 JOOQRecords 的加载程序 API。

dslContext
    .insertInto(FOO)
    .columns(FOO.A, FOO.B)
    .select(
        select(A, B)
        .from(BAR))
    .execute();

【问题讨论】:

您选择的方法是最有效的方法之一:让数据库完成所有工作。你遇到了什么问题? 我正在使用 RDS Postgresql,当查询正在执行时,db 进程被终止,并显示此消息“由于内存消耗过多,数据库进程被操作系统杀死” 【参考方案1】:

这并不是一个严格的 jOOQ 问题,因为在 JDBC 甚至在存储过程中编写等效查询时会遇到同样的问题。这种批量数据传输操作通常是使用 SQL 在表之间复制数据的最有效方式。可能有其他可用的工具绕过 SQL 层(例如pg_dump),但对于 SQL,这是最佳选择。

如果您没有足够的资源一次性运行所有内容,您可以使用不同的技术将数据集划分为多个块:

通过传输各个日期范围的数据 通过传输各个 ID 范围的数据 通过使用keyset pagination

如上所述对数据进行分区时,还要检查是否可以减小事务大小,例如每次提交最多 1000 行。这不是精确的科学,您必须根据经验为您的特定系统找到合适的块和事务大小。

使用所有这些方法,ACID 不再得到保证,因此如果您的源数据在移动过程中被修改,您必须以某种方式检测到并“修复它”(例如,通过标记已移动的行)

或者,只是为系统添加更多内存。

【讨论】:

以上是关于JOOQ 插入到具有大量记录的选择中的主要内容,如果未能解决你的问题,请参考以下文章

使用 jOOQ 使用正确的类型转换从 values() 中选择插入

JOOQ 插入记录列表

连接多个表并选择共同字段时返回自定义 JOOQ 记录

Jooq 从多对多关系中选择 pojos

使用 JooQ 从 CSV 中“批量插入”并同时跟踪插入的记录?

Jooq batchInsert()。execute()