jOOQ批量插入不一致
jOOQ batch insertion inconsistency
在 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 所说的“批量更新”)是有区别的。
This page of the manual about data import explains the difference.
- Bulk size: The number of rows that are sent to the server in one SQL statement.
- Batch size: The number of statements that are sent to the server in one JDBC statement batch.
这些是根本不同的东西。两者都有助于提高性能。批量数据处理通过帮助 RDBMS 优化资源分配算法来实现,因为它知道将要插入 10 条记录。批处理数据处理通过减少客户端和服务器之间的往返次数来实现。任何一种方法是否对任何给定的 RDBMS 都有很大影响显然是供应商特定的。
换句话说,您的两种方法都按预期工作。
在 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 所说的“批量更新”)是有区别的。
This page of the manual about data import explains the difference.
- Bulk size: The number of rows that are sent to the server in one SQL statement.
- Batch size: The number of statements that are sent to the server in one JDBC statement batch.
这些是根本不同的东西。两者都有助于提高性能。批量数据处理通过帮助 RDBMS 优化资源分配算法来实现,因为它知道将要插入 10 条记录。批处理数据处理通过减少客户端和服务器之间的往返次数来实现。任何一种方法是否对任何给定的 RDBMS 都有很大影响显然是供应商特定的。
换句话说,您的两种方法都按预期工作。