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

时间:2017-07-05 21:35:13

标签: java spring spring-mvc spring-boot spring-data-jpa

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

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

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

旁注:

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

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

2 个答案:

答案 0 :(得分:2)

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

Spring数据CrudRepository有一个save方法,需要Iterable,所以你也可以使用它,虽然你必须花时间查看它的表现如何JdbcTemplate。使用Spring Data,步骤如下(从here获取并进行一些编辑)

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

    @Id
    @GeneratedValue(generator = "generator")
    @GenericGenerator(name = "generator", strategy = "increment")
    
  3. 使用save(Iterable<S> entities)的{​​{1}}方法保存数据。

  4. 使用:CrudRepository配置。
  5. 解决方案#2的代码是here

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

    HTH。

答案 1 :(得分:-1)

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