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() 中选择插入