繁体   English   中英

Jooq批记录插入

[英]Jooq batch record insert

我目前正试图批量插入许多记录(~2000)和Jooq的batchInsert没有做我想要的。

我正在将POJO转换为UpdatableRecords,然后我正在执行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吗? 有任何想法吗? ;)

jOOQ的DSLContext.batchInsert()为每组具有相同生成的SQL字符串的连续记录创建一个JDBC批处理语句(不幸的是,Javadoc没有正式定义它)。

当您的记录如下所示时,这可能会变成一个问题:

+------+--------+--------+
| COL1 | COL2   | COL3   |
+------+--------+--------+
| 1*   | {null} | {null} |
| 2*   | B*     | {null} |
| 3*   | {null} | C*     |
| 4*   | D*     | D*     |
+------+--------+--------+

..因为在这种情况下,生成的SQL字符串将如下所示:

INSERT INTO t (col1) VALUES (?);
INSERT INTO t (col1, col2) VALUES (?, ?);
INSERT INTO t (col1, col3) VALUES (?, ?);
INSERT INTO t (col1, col2, col3) VALUES (?, ?, ?);

这种默认行为的原因是这是保证... DEFAULT行为的唯一方法。 与在SQL DEFAULT 我在这里给出了这种行为的基本原理

考虑到这一点,并且由于每个连续的SQL字符串不同,遗憾的是,插入不会像您预期的那样作为单个批处理进行批处理。

解决方案1:确保所有更改的标志都为true

强制所有INSERT语句相同的一种方法是将每个单独记录的所有已更改标志设置为true

for (Record r : records)
    r.changed(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()标志。 一些相关问题:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM