java Jooq批记录插入
我目前正试图批量插入许多记录(~2000条),而Jooq的batchInsert并不是我想要的
我将POJO转换为可更新记录,然后执行batchInsert,这是对每个记录执行insert。因此,Jooq对每个批插入进行了约2000次查询,这会降低数据库性能
它正在执行以下代码(jooq的批插入):
for (int i = 0; i < records.length; i++) {
Configuration previous = ((AttachableInternal) records[i]).configuration();
try {
records[i].attach(local);
executeAction(i);
}
catch (QueryCollectorSignal e) {
Query query = e.getQuery();
String sql = e.getSQL();
// Aggregate executable queries by identical SQL
if (query.isExecutable()) {
List<Query> list = queries.get(sql);
if (list == null) {
list = new ArrayList<Query>();
queries.put(sql, list);
}
list.add(query);
}
}
finally {
records[i].attach(previous);
}
}
我可以这样做(因为Jooq在内部也做同样的事情):
records.forEach(UpdatableRecord::insert);
而不是:
jooq.batchInsert(records).execute();
如何让Jooq以批处理模式创建新记录?我是否应该将记录转换为绑定查询,然后调用batchInsert?有什么想法吗?;)
# 1 楼答案
jOOQ的^{} 使用相同的生成的SQL字符串为每组连续记录创建一个JDBC批处理语句(遗憾的是,Javadoc没有正式定义这一点)
当您的记录如下所示时,这可能会变成一个问题:
。。因为在这种情况下,生成的SQL字符串将如下所示:
这种违约行为的原因是,这是保证
DEFAULT
行为。就像SQLDEFAULT
I gave a rationale of this behaviour here考虑到这一点,并且由于每个连续的SQL字符串都是不同的,很遗憾,插入并没有像您预期的那样作为单个批次进行批处理
解决方案1:确保所有更改的标志都是
true
强制所有
INSERT
语句相同的一种方法是将每个单独记录的所有更改标志设置为true
:现在,所有SQL字符串都将是相同的
解决方案2:使用
Loader
API您可以导入数据(并在其中指定批量大小),而不是批处理。有关详细信息,请参阅手册中有关导入记录的部分:
https://www.jooq.org/doc/latest/manual/sql-execution/importing/importing-records
解决方案3:改用批处理语句
在使用
batchInsert()
时,使用TableRecords
非常方便。当然,您可以手动生成INSERT
语句,并使用jOOQ的批处理语句API批处理各个绑定变量:https://www.jooq.org/doc/latest/manual/sql-execution/batch-execution
关于性能的说明
关于
DSLContext.batchInsert()
和类似的API,有几个悬而未决的问题。为每个记录生成SQL字符串的客户端算法效率低下,将来可能会直接依赖changed()
标志进行更改。一些相关问题: