【问题标题】:Looking for a way to speed up the data update with Spring Data JPA寻找一种使用 Spring Data JPA 加速数据更新的方法
【发布时间】: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是错误的,可能是配置错误。 我可以以某种方式修复它吗? 有什么办法可以提高更新速度?

  1. 最后...可能是我测试过的最重要的尝试。

事务完成后创建运行后,我认为实体被分离并需要合并(他们在这里声明:Does JPA's commit() method make entity detached?) 我什至重新启动了码头。 我的更新代码所做的唯一一件事就是在更新运行期间设置一个新值。 该新值被神奇地转移到数据库中,而无需调用存储库方法 saveAndFlash(即 entitymanager.merge):) 唉,虽然处理速度没有提高......

【问题讨论】:

    标签: hibernate spring-data-jpa entitymanager


    【解决方案1】:

    由于没有人提出任何解决方案,所以让我说说最终对我有什么帮助

    我将以下内容注入到服务类中:

    @PersistenceContext
    private EntityManager entityManager;
    

    并调用

    entityManager.clear();
    

    每 1000 条记录后

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多