java程序sql插入数据慢问题

【 使用环境 】生产环境
【 OB or 其他组件 】ob
【 使用版本 】4.0
【问题描述】
java程序执行百万级sql插入,执行时间需要10多分钟 - #24,来自 刘红伟
老师给出的回答, 经测试还是有问题。
代码已经是批量导入了,还是执行的很慢。
ocp显示真正更新的行数是1行



麻烦值班老师帮看下

把entityManager的代码也贴一下,从截图来看,看不出“代码已经是批量导入了”

entityManager是使用的jar包的,您是想要导入的代码吗?真正执行导入的就是上面的代码

jdbc的url发一下

jdbc:oceanbase://****:2883/?rewriteBatchedStatements=TRUE&allowMultiQueries=TRUE&useLocalSessionState=TRUE&useUnicode=TRUE&useServerPrepStmts=true&cachePrepStmts=true&useCursorFetch=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false

加了事务注解,这是一整个导入完成才提交的事务,相当于很大的事务啊。
看能不能拆分成小事务测试一下呢?
或者先去掉事务注解测试一下是否有性能提升。
在看要不要拆小事务。

老师,我们这个事务不是1000条执行一次吗?是所有的97万执行完了才执行一次事务吗?

你的注解在方法上,整个方法执行完才提交的事务。
1000条执行executeBatch执行了,整个事务并没有提交commit。

取消注解,手动commit测试下吗?

取消注解,每次数据库操作会是自动提交的事务。你不用手动commit.

好的,我们试下

老师,我们这取消事务了,代码没法执行了啊,不清楚您说的方式

主要从现在的代码看上去,你的执行方式是这样:

begin;
insert t1 values();
insert t1 values();
insert t1 values();
commit;

这样每条sql就是只影响一行;所以希望确认客户端连接代码是不是这样;

总数是97万,我们想执行970次,每次是提交1000个,影响970行。
现在只影响一行,和我们代码的逻辑不对。

事务注解去掉报错,是不是哪里封装的有问题啊?不行将调用单独写方法,public,加注解试试。没有你的代码,测试不了啊。

每条sql就是只影响一行,像是批量rewriteBatchedStatements=TRUE没有生效,试试小写?

代码:
@Transactional(readOnly = false)
public void batchInsertAndUpdate(List list) {
int size = list.size();
for (int i = 0; i < size; i++) {
entityManager.persist(entityManager.merge(list.get(i)));
// 每1000条数据执行一次,或者最后不足1000条时执行
if (i>0&& (i % 1000 == 0 || i==(size-1))) {
System.out.println("===================="+i);
entityManager.flush();
entityManager.clear();
}
}
}
取消上面的注解会报错,提示添加注解。

我们试下小写true的

试了小写的,还是不行。
老师,现在问题好像是最后一起插入97万的,正常应该是1000条插入一次,然后刷新数据库就可以看见的,现在是全部执行完了刷新数据库才能看见数据。

我上边就说了,你这在执行方法上加的事务注解,就是整个方法执行结束,才会事务提交。
ob数据库默认读已提交,只有事务提交才能看到。

我也写了拆分方式,你要改写方法的,加两个public方法:
将调用entityManager.persist(entityManager.merge(list.get(i)));单独写方法,public,加注解。
将entityManager.flush();entityManager.clear();单独写方法,public,加注解。

方法上注解去掉,改用调这两方法。但是你要考虑如果失败部分的如何处理。打日志?重新入库?等等异常情况

好的,我们测试下,麻烦老师了

老师,经过拆分确实是可以实现一点点的插入了,刷新数据库也可以观察到。
但是ocp显示怎么还是一行啊?


速度方面也没有快。
代码如下


这种方式感觉还是一条条的插入,不是1000条插入一次