处理大型CSV文件的最佳方法是什么?

时间:2016-07-18 05:15:05

标签: java sql-server csv architecture

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

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

总体而言,4 CSV s的大小为1.5 Gb。但是我们应该考虑到每15分钟生成一些文件。这些数据也应该汇总(不是那么难的过程,但肯定需要时间)。我需要快速回复。 我正在考虑如何将这些数据和整体数据存储在实现中。

我们有java堆叠。数据库是MS SQL Standard。根据我的测量MS SQL Standard,其他应用程序无法处理此类负载。我想到了什么:

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

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

编辑#1

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

4 个答案:

答案 0 :(得分:1)

您可以考虑查看Apache Spark项目。验证和策划数据后,可以使用Presto运行查询。

答案 1 :(得分:1)

您可以使用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();

}

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

希望这有帮助。

答案 2 :(得分:1)

好。花了一些时间解决这个问题(包括阅读,咨询,试验,做几个PoC)。我提出了以下解决方案。

铊组成; dr

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

工具Apache Spark非常适合此类任务。很好的表现。

DB

关于数据库,决定是一件很重要的事情。选择什么以及将来如何使用这么多数据。它绝对应该是一个单独的服务器实例,以便不在主数据库实例上生成额外的负载而不阻止其他应用程序。

的NoSQL

我在这里考虑了Cassandra的用法,但这个解决方案现在太复杂了。 Cassandra没有即席查询。 Cassandra数据存储层基本上是一个键值存储系统。这意味着您必须围绕所需的查询“建模”数据,而不是围绕数据本身的结构。

RDBMS

我不想在这里过度工程。我在这里停止了选择。

MS SQL Server

这是一种方法,但这里的重大缺点是定价。很贵。考虑到我们的硬件,企业版需要花费很多钱。关于定价,您可以阅读此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

答案 3 :(得分:0)

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