首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jooq批记录插入

问Jooq批记录插入
EN

Stack Overflow用户
提问于 2017-07-24 14:49:21
回答 1查看 10.8K关注 0票数 7

我目前正在尝试批量插入许多记录(~2000),但是Jooq的batchInsert没有完成我想要的操作。

我将POJO转换为UpdatableRecords,然后执行batchInsert,这将对每条记录执行insert。因此,Jooq为每个批插入操作执行大约2000个查询,这会扼杀数据库性能。

它正在执行这段代码(jooq的批量插入):

代码语言:javascript
复制
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在内部也在做同样的事情):

代码语言:javascript
复制
records.forEach(UpdatableRecord::insert);

而不是:

代码语言:javascript
复制
jooq.batchInsert(records).execute();

如何告诉Jooq在批处理模式下创建新记录?是否应该将记录转换为bind查询,然后调用batchInsert?有什么想法吗?;)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-24 19:24:20

Javadoc为每组连续记录创建一条JDBC批处理语句(不幸的是,DSLContext.batchInsert()没有正式定义这一点)。

当您的记录看起来像这样时,这可能会变成一个问题:

代码语言:javascript
复制
+------+--------+--------+
| COL1 | COL2   | COL3   |
+------+--------+--------+
| 1*   | {null} | {null} |
| 2*   | B*     | {null} |
| 3*   | {null} | C*     |
| 4*   | D*     | D*     |
+------+--------+--------+

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

代码语言:javascript
复制
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中一样。I gave a rationale of this behaviour here。

考虑到这一点,由于每个连续的SQL字符串都是不同的,不幸的是,插入没有像您希望的那样作为单个批处理进行批处理。

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

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

代码语言:javascript
复制
for (Record r : records)
    r.changed(true);

现在,所有的SQL字符串将是相同的。

解决方案2:使用Loader应用编程接口

您可以导入数据(并在其中指定批处理大小),而不是批处理。有关详细信息,请参阅手册中关于导入记录的部分:

https://www.jooq.org/doc/latest/manual/sql-execution/importing/importing-records

解决方案3:改用批处理语句

在使用TableRecords时,batchInsert()的使用非常方便。当然,您也可以手动生成INSERT语句,并使用jOOQ的批处理语句API对各个绑定变量进行批处理:

https://www.jooq.org/doc/latest/manual/sql-execution/batch-execution

关于性能的说明

关于DSLContext.batchInsert()和类似的应用程序接口,有几个开放的问题。为每个单独的记录生成SQL字符串的客户端算法效率很低,将来可能会更改,直接依赖于changed()标志。一些相关问题:

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45274242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档