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

问题描述 投票:0回答:3

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

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

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

旁注:

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

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

java spring spring-mvc spring-boot spring-data-jpa
3个回答
5
投票

This GitHub 存储库比较了 5 种不同的批量插入数据的方法。附件。对他来说,使用

JdbcTemplate
是最快的(他声称在 1.79 [+- 0.50] 秒内记录了 500000 条记录)。如果您将
JdbcTemplate
与 Spring Data 一起使用,则需要创建一个自定义存储库;有关详细说明,请参阅文档中的this部分。

Spring Data

CrudRepository
有一个
save
方法,它需要一个
Iterable
,所以你也可以使用它,尽管你必须计时来看看它相对于
JdbcTemplate
的表现如何。使用 Spring Data,步骤如下(取自here,经过一些编辑)

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

    @Id
    @GeneratedValue(generator = "generator")
    @GenericGenerator(name = "generator", strategy = "increment")
    
  3. 使用:

    save(Iterable<S> entities)
    CrudRepository
    方法来保存数据。

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

解决方案 #2 的代码是here

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

HTH.


0
投票

如果您使用的是 SQLServer,只需创建一个 SSiS 包来查找该文件,当它出现时,只需抓取它并加载它,然后重命名该文件。这使得它可以一次性构建并执行一百万次,并且 SSIS 可以相当快地加载大量数据。 瑞克


0
投票

萨玛,

我正在开发类似的代码,我需要通过 REST API 导入和导出 500000 行,使用 JPA,我已经实现了该代码,并且需要很长时间才能处理 100000 行的 6 小时,我有多个用于映射的子实体。

您能分享一下解决同样情况的方法吗?

© www.soinside.com 2019 - 2024. All rights reserved.