为啥在单个记录上调用 Spring Data JPA save() 而不是在记录列表上调用它时速度很慢?

Posted

技术标签:

【中文标题】为啥在单个记录上调用 Spring Data JPA save() 而不是在记录列表上调用它时速度很慢?【英文标题】:Why Spring Data JPA's save() is slow when called on a single record vs calling it on a list of records?为什么在单个记录上调用 Spring Data JPA save() 而不是在记录列表上调用它时速度很慢? 【发布时间】:2018-05-08 07:51:00 【问题描述】:

single record vs calling save on a list of records 上使用SimpleJpaRepository 中的save 函数时,我的时间大大减少。

下面的循环花费10list 长。

    for (Record r : csvRecords) 
            myRepository.save(r);
    

myRepository 根本没有任何 @Transactional 注释。 但是与上面的相比,下面的循环速度非常快。

List<Record> myArray = new ArrayList();
for (Record r : csvRecords) 
        myArray.add(r);

myRepository.save(myArray);

如果我们查看SimpleJpaRepository 中的save 实现

@Transactional
public <S extends T> List<S> save(Iterable<S> entities) 

   List<S> result = new ArrayList<S>();

   if (entities == null) 
      return result;
   

   for (S entity : entities) 
      result.add(save(entity));
   

   return result;

这个实现只是屏蔽了单个 save 操作,所以如果我首先将数据存储在缓冲区中或者我在每条记录上调用 save 应该没有任何区别,因此速度增加对于我。

编辑: 使用docs.spring.io/autorepo/docs/spring-data-commons/1.5.1.RELEA‌​SE/ 版本。

【问题讨论】:

你确定你没有使用SimpleJpaRepository 的子类,它用更优化的东西覆盖save(Iterable) 方法吗? 如果对 save() 进行 10 次单次调用,您将执行 10 次事务,但如果使用 10 条记录列表调用 save(),则只有一次。这可能是您观察的原因。 JPA API 没有这样的“保存”方法。也许您的意思是“Spring Data JPA”,它不是 JPA API。 @DN1 感谢您的评论。 【参考方案1】:

在单个条目的情况下,您打开 10 笔交易 - 需要打开和关闭;在List 的情况下,save(singleEntry)(在saveAll 内部使用)将重新使用已经打开的事务,因此它是一个打开和关闭的单一事务。顺便说一句,如果我正确地重新调用它的saveAll(Iterable) not save(Iterable)

【讨论】:

感谢您指出! docs.spring.io/autorepo/docs/spring-data-commons/1.5.1.RELEASE/… 显然我使用的是旧版本。 @Oleg 啊!这是有道理的。

以上是关于为啥在单个记录上调用 Spring Data JPA save() 而不是在记录列表上调用它时速度很慢?的主要内容,如果未能解决你的问题,请参考以下文章

spring-data-jpa循环保存数据,为啥只保存了最后一条数据

为啥分页查询比使用 Spring Data 的普通查询慢?

Spring data JPA:未提交每条记录的事务

为啥我不能在 super 上调用 Core Data Accessors?

为啥在 Spring Boot 中超类上的 @Bean 泛型创建方法比子类上的方法调用晚?

使用Spring Data获取单个NonNull值