【问题标题】:Spring Boot JPA saveAll() inserting to database extremely slowlySpring Boot JPA saveAll()非常慢地插入数据库
【发布时间】:2020-04-11 12:55:42
【问题描述】:

我将 Spring Boot 与 Hibernate 结合使用来为一个简单的 Web 应用程序创建 RESTful API,在该应用程序中我读取一个 .csv 文件并将每一行插入到一个 mysql 数据库表中。我能够成功 这样做,但任何大型 csv 文件都需要很长时间。我知道最好批量插入语句以减少数量 交易,但我认为我不会用我拥有的当前代码来实现这一点。这就是我目前正在做的事情(工作但非常缓慢):

CsvUploaderController.java

public class CsvUploaderController {

    // CsvUploader Repository definition:
    // @Repository
    // public interface CsvUploaderRepository extends JpaRepository<CityObj, Integer>
    @Autowired
    CsvUploaderRepository csvUploaderRepository;

    // gets called by front end with the .csv file data
    @PutMapping("/upload_csv")
    public List<CityObj> uploadCsv(@RequestBody Object data) {
        // unpackCSV converts an arrayList of Objects to a List of CityObj
        List<CityObj> unpackedCSV = unpackCSV((ArrayList<Object>) data);
        csvUploaderRepository.deleteAll(); // delete all rows in table currently. Not sure if this is relevent to issue

        // save all items as rows in my database
        return csvUploaderRepository.saveAll(unpackedCSV); // this is where it takes forever to complete
    }
    ...
}

application.properties:

spring.datasource.url=jdbc:mysql://url.to.my.database
spring.datasource.username=myusername
spring.datasource.password=weirdpassword
spring.datasource.hikari.maximumPoolSize = 5

spring.jpa.properties.hibernate.generate_statistics=true 
spring.jpa.properties.hibernate.jdbc.batch_size=20 // I've tried playing around with different values. Hasnt helped
#spring.jpa.properties.hibernate.order_inserts=true // I've also tried using this but not sure what it does and didnt help

我做错了什么?如何提高插入的性能?我对 saveAll() 的理解是否错误?我的问题与这里描述的非常相似:Spring boot 2 upgrade - spring boot data jpa saveAll() very slow

【问题讨论】:

  • spring-batch 提供了开箱即用的功能,而不是自己做。
  • 如果您所做的只是在单个表中执行插入操作,那么 JPA 几乎不会为您做任何事情,只会让过程变得更慢和更复杂。使用JdbcTemplate 执行批量插入,而无需先将它们转换为对象。
  • 你解决了吗?

标签: mysql hibernate spring-boot jpa spring-data-jpa


【解决方案1】:

您可以通过调整 MySQL 的 HikariCP 配置来获得一些性能:https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration

由于saveAll() 在内部只是循环遍历列表,您可以手动执行循环并每 20 个实体刷新一次以减少持久性上下文的压力。

正确完成批处理当然会有所帮助。

最后,最快的方法将是带有JdbcTemplate 和多值插入的纯 SQL,例如:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 2019-01-14
    • 2017-08-03
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2019-03-01
    • 2021-02-25
    相关资源
    最近更新 更多