Я использую Spring Boot вместе с Hibernate для создания 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 - данные весенней загрузки jpa saveAll () очень медленно

2
Isaac Perez 19 Дек 2019 в 01:48
 – 
JB Nizet
19 Дек 2019 в 01:58
Вместо того, чтобы делать это самостоятельно, spring -batch предоставляет эту функциональность из коробки.
 – 
Sagar Ahuja
19 Дек 2019 в 09:16
1
Если все, что вы делаете, - это вставляете в одну таблицу, JPA почти ничего не делает для вас, кроме как замедляет и усложняет процесс. Используйте JdbcTemplate для выполнения пакетных вставок без предварительного преобразования их в объекты.
 – 
Jens Schauder
19 Дек 2019 в 09:30
Ты решил это?
 – 
afe
4 Авг 2020 в 09:37

1 ответ

Вы можете повысить производительность, настроив конфигурацию HikariCP для MySQL: https://github.com/ brettwooldridge / HikariCP / wiki / MySQL-Configuration

Поскольку saveAll() внутренне просто повторяет цикл по списку, вы можете выполнить цикл вручную и сбросить каждые 20 объектов, чтобы уменьшить нагрузку на контекст постоянства.

Правильная дозировка, конечно, поможет.

В конце самый быстрый метод будет простым SQL с JdbcTemplate и многозначными INSERT, такими как:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
2
Robert Niestroj 19 Дек 2019 в 02:19