【问题标题】:What is the best way to process large CSV files?处理大型 CSV 文件的最佳方法是什么?
【发布时间】:2016-08-23 18:53:33
【问题描述】:

我有一个每天生成大量数据的第三方系统(那些是存储在 FTP 上的 CSV 文件)。正在生成 3 种类型的文件:

  • 每 15 分钟(2 个文件)。这些文件非常小 (~2 Mb)
  • 每天下午 5 点 (~200 - 300 Mb)
  • 每个午夜(这个CSV文件大约是1 Gb

4CSVs 的总大小是1.5 Gb。但我们应该考虑到有些文件每 15 分钟生成一次。这些数据也应该汇总(不是那么难的过程,但肯定需要时间)。我需要快速响应。 我正在考虑如何存储这些数据并总体上实现。

我们有java 堆栈。数据库是MS SQL Standard。从我的测量结果来看,MS SQL Standard 与其他应用程序不会处理这样的负载。我想到了什么:

  • 这可能是使用单独的服务器升级到 MS SQL Enterprise
  • 在单独的服务器上使用PostgreSQL。目前我正在为这种方法开发 PoC。

你会在这里推荐什么?可能有更好的选择。

编辑#1

那些大文件是每天的新数据。

【问题讨论】:

  • 1GB CSV。那将是一个巨大的负担。我敢打赌,前一天有很多重复的记录。如果您可以联系生成文件的人员,我们可能需要要求他们仅向您发送更改后的数据。这就是大多数系统为减少负载所做的事情。
  • 是的,你是对的。在这种情况下,负载是巨大的。我还没有完全讨论过关于数据的那些要求,但这就是我从规范中得到的。从规范来看,没有可以用作更新文件的中间文件。它每次都包含新的/更新的数据。如果无法更新 - 我希望这些数据每天都会过时。
  • 我使用 BULK LOAD Queries + 过程导入了一个 MAX 5 MB 的 csv 文件,我发现有时这是一个 LOAD。如果不拉扯我的头发,我无法想象一个 1 GB 文件的场景。 SQL-Sever 无法执行大小为 200MB 的 .sql 文件。想知道在读取之前需要处理的 1GB csv 文件会发生什么。
  • 请详细说明这个大文件:它每天都有所有新数据还是累积的?
  • “过程”是什么意思?是导入/更新/交叉处理还是命令?

标签: java sql-server csv architecture


【解决方案1】:

好的。在花了一些时间解决这个问题之后(它包括阅读、咨询、实验、做几个 PoC)。我想出了以下解决方案。

Tl;博士

数据库PostgreSQL,因为它适用于 CSV,免费且开源。

工具Apache Spark 非常适合此类任务。表现不错。

数据库

关于数据库,决定是一件很重要的事情。选择什么以及将来如何处理如此大量的数据。它绝对应该是一个单独的服务器实例,以免在主数据库实例上产生额外的负载,也不会阻塞其他应用程序。

NoSQL

我在这里想过Cassandra的用法,但是这个解决方案现在太复杂了。 Cassandra 没有临时查询。 Cassandra数据存储层基本上是一个key-value存储系统。这意味着您必须围绕您需要的查询“建模”您的数据,而不是围绕数据本身的结构。

关系数据库

我不想在这里过度设计。我在这里停止了选择。

MS SQL 服务器

这是一条路要走,但这里最大的缺点是定价。相当昂贵。考虑到我们的硬件,企业版要花很多钱。关于定价,您可以阅读此policy document

这里的另一个缺点是对 CSV 文件的支持。这将是我们这里的主要数据源。 MS SQL Server 既不能导入也不能导出 CSV。

  • MS SQL Server 静默截断文本字段。

  • MS SQL Server 的文本编码处理出错。

MS SQL Server 抛出错误消息,因为它不理解引用或转义。 有关该比较的更多信息,请参阅文章 PostgreSQL vs. MS SQL Server

PostgreSQL

这个数据库是一个成熟的产品,也经过了很好的测试。我从其他人那里听到了很多积极的反馈(当然,也有一些权衡)。它具有更经典的 SQL 语法,良好的 CSV 支持,而且它是开源的。

值得一提的是SSMSPGAdmin 好很多。 SSMS 具有自动完成功能,多个结果(当您运行多个查询并同时获得多个结果时,但在 PGAdmin 中您只能获得最后一个)。

无论如何,我现在使用的是 JetBrains 的 DataGrip

处理工具

我浏览过Spring BatchApache SparkSpring Batch 有点太低级了,无法用于此任务,而且 Apache Spark 提供了在将来需要时更容易扩展的能力。无论如何,Spring Batch 也可以完成这项工作。

关于Apache Spark的例子,代码可以在learning-spark项目中找到。 我现在的选择是Apache Spark

【讨论】:

    【解决方案2】:

    您可以考虑研究Apache Spark 项目。验证和整理数据后,可以使用Presto 运行查询。

    【讨论】:

      【解决方案3】:

      您可以使用 uniVocity-parsers 尽可能快地处理 CSV,因为这个库附带了 fastest CSV 解析器。我是这个库的作者,它是开源和免费的(Apache V2 许可证)

      现在要将数据加载到数据库中,您可以尝试univocity framework(商业)。我们使用它非常快速地将大量数据加载到 SQL Server 和 PostgreSQL 等数据库中 - 从 25K 到 200K 行/秒,具体取决于数据库及其配置。

      下面是一个简单的示例,说明如何从 CSV 迁移代码:

      public static void main(String ... args){
          //Configure CSV input directory
          CsvDataStoreConfiguration csv = new CsvDataStoreConfiguration("csv");
          csv.addEntitiesFromDirectory(new File("/path/to/csv/dir/"), "ISO-8859-1");
      
          //should grab column names from CSV files
          csv.getDefaultEntityConfiguration().setHeaderExtractionEnabled(true);
      
          javax.sql.DataSource dataSource = connectToDatabaseAndGetDataSource(); //specific to your environment
      
          //Configures the target database
          JdbcDataStoreConfiguration database = new JdbcDataStoreConfiguration("database", dataSource);
      
          //Use only for postgres - their JDBC driver requires us to convert the input Strings from the CSV to the correct column types.
          database.getDefaultEntityConfiguration().setParameterConversionEnabled(true);
      
          DataIntegrationEngine engine = Univocity.getEngine(new EngineConfiguration(csv, database));
      
          //Creates a mapping between data stores "csv" and "database"
          DataStoreMapping mapping = engine.map(csv, database);
      
          // if names of CSV files and their columns match database tables an their columns
          // we can detect the mappings from one to the other automatically
          mapping.autodetectMappings();
      
          //loads the database.
          engine.executeCycle();
      
      }
      

      为了提高性能,该框架允许您管理数据库架构并执行删除约束和索引等操作、加载数据并重新创建它们。如果您需要,也很好地支持数据和模式转换。

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        Pentaho 数据集成(或类似的 ETL 工具)可以处理将数据导入 SQL 数据库并且可以进行动态聚合。 PDI 有一个社区版,可以独立运行,也可以通过 Java API 运行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-11
          • 2018-12-03
          • 2020-03-16
          • 2019-01-30
          • 2017-04-15
          • 1970-01-01
          • 2020-07-28
          • 1970-01-01
          相关资源
          最近更新 更多