Java Spring:如何高效地从CSV文件中读取和保存大量数据?

V. *_*mma 3 java spring spring-mvc spring-data-jpa spring-boot

我正在 Java Spring 中开发一个 Web 应用程序,我希望用户能够从前端上传 CSV 文件,然后查看导入过程的实时进度,导入后他应该能够搜索单个条目从导入的数据。

导入过程包括实际上传文件(通过 REST API POST 请求发送),然后读取文件并将其内容保存到数据库中,以便用户能够从此数据中进行搜索。

将数据保存到数据库的最快方法是什么?仅循环遍历各行并创建一个新的类对象并通过 JPARepository 为每行保存它会花费太多时间。10000 行大约需要 90 秒。我需要让它变得更快。我需要在合理的时间内添加 200k 行。

附注:

我看到了使用 Reactor 的异步方法。这应该会更快,因为它使用多个线程,并且保存行的顺序基本上并不重要(尽管数据在 CSV 中具有 ID)。

然后我还看到了 Spring Batch 作业,但所有示例都使用 SQL。我正在使用存储库,所以我不确定是否可以使用它或者它是否是最好的方法。

Abh*_*kar 5

GitHub 存储库比较了 5 种不同的批量插入数据的方法。附件。对他来说,使用JdbcTemplate是最快的(他声称在 1.79 [+- 0.50] 秒内完成 500000 条记录)。如果您使用JdbcTemplateSpring Data,则需要创建一个自定义存储库;有关详细说明,请参阅文档中的此部分。

Spring DataCrudRepository有一个save接受 的方法Iterable,因此您也可以使用它,尽管您必须计时以了解它如何针对JdbcTemplate. 使用 Spring Data,步骤如下(取自此处并进行一些编辑)

  1. 添加:rewriteBatchedStatements=true到连接字符串的末尾。
  2. 确保您使用的生成器支持实体中的批处理。例如

    @Id
    @GeneratedValue(generator = "generator")
    @GenericGenerator(name = "generator", strategy = "increment")
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用:save(Iterable<S> entities)方法来CrudRepository保存数据。

  4. 使用:hibernate.jdbc.batch_size配置。

解决方案#2 的代码在这里

至于使用多个线程,请记住,从多个线程写入数据库中的同一个表可能会产生表级争用并产生更糟糕的结果。你必须尝试并计时。如何使用 Reactor 项目编写多线程代码是一个完全独立的主题,超出了此处的范围。

HTH。