use*_*939 5 jpa toplink toplink-essentials
我正在尝试使用 JPA 对大型对象图进行级联保存。例如(我的对象图有点大但足够接近):
@Entity
@Table(name="a")
public class A {
private long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "a")
private Collection<B> bs;
}
@Entity
@Table(name="b")
public class B {
private long id;
@ManyToOne
private A a;
}
Run Code Online (Sandbox Code Playgroud)
所以我试图保留一个包含 100 多个 B 的集合的 A。代码只是
em.persist(a);
Run Code Online (Sandbox Code Playgroud)
问题是,它很慢。我的保存大约需要 1300 毫秒。我查看了正在生成的 SQL,它的效率非常低。像这样的东西:
select a_seq.nextval from dual;
select b_seq.nextval from dual;
select b_seq.nextval from dual;
select b_seq.nextval from dual;
...
insert into a (id) values (1);
insert into b (id, fk) values (1, 1);
insert into b (id, fk) values (2, 1);
insert into b (id, fk) values (3, 1);
...
Run Code Online (Sandbox Code Playgroud)
目前使用 toplink 作为持久性提供者,但我也尝试过 eclipselink 和 hibernate。后端是oracle 11g。问题实际上是如何将 sql 放在一起。这些操作中的每一个都是离散完成的,而不是批量完成的,所以如果我的应用服务器和数据库服务器之间的网络延迟甚至是 5 毫秒,那么执行 200 次离散操作会增加 1 秒。我试过增加我的序列的分配大小,但这只是有点帮助。我也试过直接 JDBC 作为批处理语句:
for...{
statement = connection.prepareStatement(sql);
statement.addBatch();
}
statement.executeBatch();
Run Code Online (Sandbox Code Playgroud)
对于我的数据模型,直接 JDBC 批处理大约需要 33 毫秒。对于 100 多个插入,Oracle 本身需要 5 毫秒。
有没有办法让 JPA(我现在坚持使用 1.0...)在不深入研究供应商特定的东西(如休眠批量插入)的情况下运行得更快?
谢谢!
解决方案是启用 JDBC 批处理,并定期刷新和清除 EntityManager(与批处理大小相同),但我不知道有供应商中立的方法来执行此操作:
使用 Hibernate,您必须设置hibernate.jdbc.batch_size配置选项。请参阅第 13 章。批处理
使用EclipseLink,看起来有批量写入模式。请参阅 Jeff Sutherland 在该线程中的帖子(也应该可以指定大小)。
根据这篇博文的评论,TopLink Essentials 中不支持批量写入:(
| 归档时间: |
|
| 查看次数: |
2350 次 |
| 最近记录: |