JOOQ批处理语句中的绑定调用次数是否有上限?

Is there an upper limit to the number of bind calls in a JOOQ batch statement?

我们在插入时使用批处理语句如下:

BatchBindStep batch = create.batch(create
   .insertInto(PERSON, ID, NAME)
   .values((Integer) null, null));

for (Person p : peopleToInsert) {
  batch.bind(p.getId(), p.getName());
}
batch.execute();

这在过去插入数千个对象时效果很好。但是,它提出了几个问题:

  1. 一个批次的.bind()调用次数有上限吗?
  2. 如果是这样,限制取决于什么?
  3. 似乎可以在执行完.execute()后再次调用.bind().execute() 会清除之前绑定的值吗?

澄清最后一个问题:执行以下代码后...

BatchBindStep batch = create.batch(create
   .insertInto(PERSON, ID, NAME)
   .values((Integer) null, null));

batch.bind(1, "A");
batch.bind(2, "B");
batch.extecute();
batch.bind(3, "C");
batch.bind(4, "D");
batch.execute();

我应该期待哪个结果?

a)        b)
ID NAME   ID NAME
-------   -------
 1 A       1 A
 2 B       2 B
 3 C       1 A
 4 D       2 B
           3 C
           4 D

不幸的是,Javadoc nor the documentation 都没有讨论这个特定的使用模式。

(我问这个特定的问题是因为如果我 .execute() 每 1000 次绑定左右以避免上述限制,我需要知道我是否可以将 batch 对象重复用于几个 .execute()来电与否。)

这个答案从 jOOQ 3.7 开始有效

  1. Is there an upper limit to the number of .bind() calls for a batch?

不在 jOOQ 中,但您的 JDBC 驱动程序/数据库服务器可能有这样的限制。

  1. If so, what does the limit depend on?

几件事:

  • jOOQ 为所有绑定变量保留一个中间缓冲区,并将它们一次性绑定到 JDBC 批处理语句。因此,您的客户端内存也可能会施加上限。但是jOOQ本身没有任何限制。
  • 您的 JDBC 驱动程序可能知道这样的限制 (see also this article on how jOOQ handles limits in non-batch statements)。已知限制是:

    • SQLite:每个语句 999 个绑定变量
    • Ingres 10.1.0:每条语句 1024 个绑定变量
    • Sybase ASE 15.5:每条语句 2000 个绑定变量
    • SQL Server 2008:每条语句 2100 个绑定变量

    我不知道 Oracle 中有任何此类限制,但可能有。

  • 插入大量数据时,批量大小并不是您唯一应该调整的东西。还有:

    • 批量大小,即每个语句插入的行数
    • 批量大小,即每批发送到服务器的语句数
    • 提交大小,即单个事务中提交的批次数

    调整插入归结为调整以上所有内容。 jOOQ 附带一个专用导入 API ,您可以在其中调整以上所有内容:http://www.jooq.org/doc/latest/manual/sql-execution/importing

  • 您还应该考虑绕过 SQL 以插入加载程序 table,例如使用 Oracle's SQL*Loader. Once you've inserted all data, you can move it to the "real table" using PL/SQL's FORALL statement,这是 PL/SQL 版本的 JDBC 批处理语句。这种方法将执行您使用 JDBC.

  • 执行的任何操作
  1. It seems to be possible to call .bind() again after having executed .execute(). Will .execute() clear previously bound values?

目前,execute() 不会清除绑定值。您需要改为创建一个新语句。这不太可能改变,因为未来的 jOOQ 版本将在其 API 设计中支持不变性。