【发布时间】:2019-07-19 06:48:57
【问题描述】:
同事们, 对于以下案例,我将不胜感激。
我们的项目基于 Spring Data JPA - 因此我的存储库实现基于 SimpleJpaRepository。
要讨论的方法在标有@Transactional 的服务中。
据我了解,如果我不介入流程,Spring 会创建实体管理器、刷新数据并提交事务。
项目两次读取和解析外部json。 第一次运行 - 给出 json 来填充表格。 第二次运行 - 具有相同大小的 json 和一些新值,用于更新表。
表在用于更新的搜索字段上有一个唯一索引。 数据对象是基本的,没有 @OneToMany 关系。
问题:第二次运行时速度急剧下降(获取更新)。 每个新处理的记录,例如 1000 条记录的处理速度都比前一个记录慢。 结果 update-run 比 create-run 耗时大约 10 倍
对于创建-运行,我使用了直接的存储库方法#save,它在#persist 和#merge 之间进行选择,仅此而已。 显然它在我的情况下选择了#persist。很可能数据被刷新,事务由 Spring 提交。 我打开了“generate_statistics”选项,有 1 个刷新和按预期创建的实体数量
我如何尝试加快更新速度:
首先,对于更新运行,我将要处理的数据切片为集合(实际上是在每个切片处理端清除的集合)并首先调用#saveAll 然后调用#flush(实际上是 em#flush) 这种方法基于这些讨论 How to improve performance of Updating data using JPA 和 HIbernate commit() and flush()
唉,花费的时间几乎是一样的, JDBC 操作的数量是相同的, 刷新次数与预期一致(例如,“pack”大小为 1000 时刷新 29 次,“pack”大小为 10 时刷新 2900 次)。 奇怪的是,这次的实体数与要更新的表中的记录数不同
日志看起来像
76545093741 nanoseconds spent executing 2860 flushes (flushing a total of 40912292 entities and 0 collections);
756096912142 nanoseconds spent executing 28592 partial-flushes (flushing a total of 408736936 entities and 408736936 collections)
40912292 个实体? 408736936 个实体和集合? 但为什么? 我还想知道那些部分冲洗是什么 - 是什么引起的?为什么他们的数字浮动?
我想知道为什么手动定期刷新没有帮助。
其次,在之前的尝试中,我使用了带有 IDENTITY 策略自动生成的主键的数据对象。
这次我决定尝试批处理。 我将 PK 生成策略更改为 SEQUENCE 并添加了一堆 Spring 属性用于批处理:
jpa:
properties:
hibernate:
jdbc:
batch_size: 50
batch_versioned_data: true
order_inserts: true
order_updates: true
在这种情况下我收到了什么日志:
250614501 nanoseconds spent preparing 28594 JDBC statements;
8759177291 nanoseconds spent executing 28592 JDBC statements;
3398281 nanoseconds spent executing 2 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
7925542816 nanoseconds spent executing 286 flushes (flushing a total of 4104092 entities and 0 collections);
794086157441 nanoseconds spent executing 28592 partial-flushes (flushing a total of 408736936 entities and 408736936 collections)
所以只有 2 个批次......而且几乎没有速度提升
显然smth是错误的,可能是配置错误。 我可以以某种方式修复它吗? 有什么办法可以提高更新速度?
- 最后...可能是我测试过的最重要的尝试。
事务完成后创建运行后,我认为实体被分离并需要合并(他们在这里声明:Does JPA's commit() method make entity detached?) 我什至重新启动了码头。 我的更新代码所做的唯一一件事就是在更新运行期间设置一个新值。 该新值被神奇地转移到数据库中,而无需调用存储库方法 saveAndFlash(即 entitymanager.merge):) 唉,虽然处理速度没有提高......
【问题讨论】:
标签: hibernate spring-data-jpa entitymanager