java - jOOQ 批量插入不一致
问题描述
在 jOOQ (v3.14.4) 中使用批量插入时,我注意到在查看 PostgreSQL (v12.6) 日志时存在一些不一致之处。执行context.batch(<query>).bind(<1st record>).bind(<2nd record>)...bind(<nth record>).execute()
日志时,显示记录实际上是一一插入,而不是一次全部插入。从 postgres 日志来看,这样做context.insert(<fields>).values(<1st record>).values(<2nd record>)...values(<nth record>)
实际上会一次性插入所有内容。它是 jOOQ 本身的错误还是我batch(...)
错误地使用了该功能?
这里有 2 个代码片段应该做同样的事情,但实际上,第一个代码片段一个接一个地插入记录,而第二个代码片段实际上是批量插入。
public void batchInsertEdges(List<EdgesRecord> edges) {
Query batchQuery = context.insertInto(Edges.EDGES,
Edges.EDGES.SOURCE_ID, Edges.EDGES.TARGET_ID, Edges.EDGES.CALL_SITES,
Edges.EDGES.METADATA)
.values((Long) null, (Long) null, (CallSiteRecord[]) null, (JSONB) null)
.onConflictOnConstraint(Keys.UNIQUE_SOURCE_TARGET).doUpdate()
.set(Edges.EDGES.CALL_SITES, Edges.EDGES.as("excluded").CALL_SITES)
.set(Edges.EDGES.METADATA, field("coalesce(edges.metadata, '{}'::jsonb) || excluded.metadata", JSONB.class));
var batchBind = context.batch(batchQuery);
for (var edge : edges) {
batchBind = batchBind.bind(edge.getSourceId(), edge.getTargetId(),
edge.getCallSites(), edge.getMetadata());
}
batchBind.execute();
}
public void batchInsertEdges(List<EdgesRecord> edges) {
var insert = context.insertInto(Edges.EDGES,
Edges.EDGES.SOURCE_ID, Edges.EDGES.TARGET_ID, Edges.EDGES.CALL_SITES, Edges.EDGES.METADATA);
for (var edge : edges) {
insert = insert.values(edge.getSourceId(), edge.getTargetId(), edge.getCallSites(), edge.getMetadata());
}
insert.onConflictOnConstraint(Keys.UNIQUE_SOURCE_TARGET).doUpdate()
.set(Edges.EDGES.CALL_SITES, Edges.EDGES.as("excluded").CALL_SITES)
.set(Edges.EDGES.METADATA, field("coalesce(edges.metadata, '{}'::jsonb) || excluded.metadata", JSONB.class))
.execute();
}
我会很感激一些帮助来弄清楚为什么第一个代码片段不能按预期工作而第二个代码片段可以。谢谢!
解决方案
“批处理”(如 JDBC 批处理)和“批量处理”(如许多 RDBMS 所说的“批量更新”)之间存在差异。
- 批量大小:一条 SQL 语句中发送到服务器的行数。
- 批处理大小:一个 JDBC 语句批处理中发送到服务器的语句数。
这些是根本不同的事情。两者都有助于提高性能。批量数据处理通过帮助 RDBMS 优化资源分配算法来实现这一点,因为它知道它将插入 10 条记录。批量数据处理通过减少客户端和服务器之间的往返次数来实现。任何一种方法是否对任何给定的 RDBMS 都有很大影响显然是特定于供应商的。
换句话说,您的两种方法都按预期工作。
推荐阅读
- sql - 如何从表中查询字符串
- java - 使用 BottomNavigationView 时仅加载一次数据
- javascript - 无法从节点js中的函数返回数据
- testing - InvalidUseOfMatchersException:参数匹配器的使用无效
- apache-spark - SparkSql 查询以从 cassandra 获取定义值的上一行和下一行
- javascript - Vuetify v-select onchange 事件返回之前选择的值而不是当前值
- angular - Conditional duplicate templateref in ng-content with selector
- python - Transforming data from Pandas dataframe to time series training data for keras LSTM
- javascript - 如何遍历路径元素并一个接一个地为每个元素设置动画?
- angularjs - GulpUglifyError:无法缩小 JavaScript 原因:SyntaxError:意外的标记名称«k»,预期的标点符号«;»