处理大型 CSV 文件的最佳方法是什么?
What is the best way to process large CSV files?
我有一个第三方系统,每天生成大量数据(这些是存储在 FTP 上的 CSV
个文件)。正在生成 3 种类型的文件:
- 每 15 分钟(2 个文件)。这些文件很小(~
2 Mb
)
- 每天下午 5 点 (~
200 - 300 Mb
)
- 每个午夜(这个
CSV
文件大约 1 Gb
)
4 CSV
的总大小是 1.5 Gb
。但我们应该考虑到某些文件每 15 分钟生成一次。这些数据也应该汇总(不是那么困难的过程,但肯定需要时间)。我需要快速响应。
我正在考虑如何存储这些数据和整体实现。
我们有 java
个堆栈。数据库是MS SQL Standard
。根据我的测量 MS SQL Standard
,其他应用程序无法处理此类负载。我想到了什么:
- 这可能是使用单独服务器升级到
MS SQL Enterprise
。
- 在单独的服务器上使用
PostgreSQL
。现在我正在为这种方法进行 PoC。
你会在这里推荐什么?可能有更好的选择。
编辑#1
这些大文件是每天的新数据。
您可以考虑查看 Apache Spark project. After validating and curating the data maybe use Presto 到 运行 个查询。
Pentaho 数据集成(或类似的 ETL 工具)可以处理将数据导入 SQL 数据库,并且可以动态进行聚合。 PDI 有社区版,可以 运行 独立版或通过 Java API.
您可以使用 uniVocity-parsers to process the CSV as fast as possible, as this library comes with the fastest CSV 解析器。我是这个库的作者,它是开源和免费的(Apache V2 许可证)
现在要将数据加载到数据库中,您可以尝试 univocity framework(商业)。我们使用它将大量数据快速加载到 SQL 服务器和 PostgreSQL 等数据库中 - 从 25K 到 200K rows/second,具体取决于数据库及其配置。
下面是一个简单示例,说明从 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();
}
为了提高性能,该框架允许您管理数据库模式并执行诸如删除约束和索引、加载数据以及重新创建它们等操作。如果您需要,数据和模式转换也得到很好的支持。
希望对您有所帮助。
好的。在花了一些时间解决这个问题之后(包括阅读、咨询、实验、做几个 PoC)。我想出了以下解决方案。
Tl;博士
数据库:PostgreSQL
因为它适用于 CSV,免费且开源。
Tool: Apache Spark 非常适合此类任务。表现不错。
数据库
关于数据库,决定是一件很重要的事情。选择什么以及将来如何处理如此大量的数据。它绝对应该是一个单独的服务器实例,以免在主数据库实例上产生额外的负载并且不会阻塞其他应用程序。
没有SQL
我在这里考虑了 Cassandra
的用法,但是现在这个解决方案太复杂了。 Cassandra
没有临时查询。 Cassandra
数据存储层基本上是一个键值存储系统。这意味着您必须围绕您需要的查询“建模”您的数据,而不是围绕数据本身的结构。
关系数据库管理系统
我不想在这里过度设计。而我在这里停止了选择。
MS SQL 服务器
这是一个可行的方法,但最大的缺点是定价。相当昂贵。考虑到我们的硬件,企业版要花很多钱。关于定价,你可以阅读这个 policy document.
这里的另一个缺点是对 CSV 文件的支持。这将是我们这里的主要数据源。 MS SQL Server
既不能导入也不能导出 CSV。
MS SQL Server
静默截断文本字段。
MS SQL Server
的文本编码处理出错。
MS SQL 服务器抛出一条错误消息,因为它不理解引号或转义。
有关该比较的更多信息,请参阅文章 PostgreSQL vs. MS SQL Server.
PostgreSQL
这个数据库是一个成熟的产品,也是久经考验的。我从其他人那里听到了很多积极的反馈(当然,也有一些权衡)。它具有更经典的 SQL 语法,良好的 CSV 支持,而且它是开源的。
值得一提的是SSMS is a way better than PGAdmin. SSMS has an autocomplete feature, multiple results (when you run several queries and get the several results at one, but in PGAdmin你只能得到最后一个)。
无论如何,我现在正在使用 JetBrains 的 DataGrip。
处理工具
我查看了 Spring 批次 和 Apache Spark。 Spring Batch 对于这个任务来说有点太低级了,而且 Apache Spark 提供了更容易扩展的能力,如果将来需要的话。无论如何,Spring Batch 也可以完成这项工作。
关于Apache Spark示例,代码可以在learning-spark项目中找到。
我现在的选择是Apache Spark。
我有一个第三方系统,每天生成大量数据(这些是存储在 FTP 上的 CSV
个文件)。正在生成 3 种类型的文件:
- 每 15 分钟(2 个文件)。这些文件很小(~
2 Mb
) - 每天下午 5 点 (~
200 - 300 Mb
) - 每个午夜(这个
CSV
文件大约1 Gb
)
4 CSV
的总大小是 1.5 Gb
。但我们应该考虑到某些文件每 15 分钟生成一次。这些数据也应该汇总(不是那么困难的过程,但肯定需要时间)。我需要快速响应。
我正在考虑如何存储这些数据和整体实现。
我们有 java
个堆栈。数据库是MS SQL Standard
。根据我的测量 MS SQL Standard
,其他应用程序无法处理此类负载。我想到了什么:
- 这可能是使用单独服务器升级到
MS SQL Enterprise
。 - 在单独的服务器上使用
PostgreSQL
。现在我正在为这种方法进行 PoC。
你会在这里推荐什么?可能有更好的选择。
编辑#1
这些大文件是每天的新数据。
您可以考虑查看 Apache Spark project. After validating and curating the data maybe use Presto 到 运行 个查询。
Pentaho 数据集成(或类似的 ETL 工具)可以处理将数据导入 SQL 数据库,并且可以动态进行聚合。 PDI 有社区版,可以 运行 独立版或通过 Java API.
您可以使用 uniVocity-parsers to process the CSV as fast as possible, as this library comes with the fastest CSV 解析器。我是这个库的作者,它是开源和免费的(Apache V2 许可证)
现在要将数据加载到数据库中,您可以尝试 univocity framework(商业)。我们使用它将大量数据快速加载到 SQL 服务器和 PostgreSQL 等数据库中 - 从 25K 到 200K rows/second,具体取决于数据库及其配置。
下面是一个简单示例,说明从 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();
}
为了提高性能,该框架允许您管理数据库模式并执行诸如删除约束和索引、加载数据以及重新创建它们等操作。如果您需要,数据和模式转换也得到很好的支持。
希望对您有所帮助。
好的。在花了一些时间解决这个问题之后(包括阅读、咨询、实验、做几个 PoC)。我想出了以下解决方案。
Tl;博士
数据库:PostgreSQL
因为它适用于 CSV,免费且开源。
Tool: Apache Spark 非常适合此类任务。表现不错。
数据库
关于数据库,决定是一件很重要的事情。选择什么以及将来如何处理如此大量的数据。它绝对应该是一个单独的服务器实例,以免在主数据库实例上产生额外的负载并且不会阻塞其他应用程序。
没有SQL
我在这里考虑了 Cassandra
的用法,但是现在这个解决方案太复杂了。 Cassandra
没有临时查询。 Cassandra
数据存储层基本上是一个键值存储系统。这意味着您必须围绕您需要的查询“建模”您的数据,而不是围绕数据本身的结构。
关系数据库管理系统
我不想在这里过度设计。而我在这里停止了选择。
MS SQL 服务器
这是一个可行的方法,但最大的缺点是定价。相当昂贵。考虑到我们的硬件,企业版要花很多钱。关于定价,你可以阅读这个 policy document.
这里的另一个缺点是对 CSV 文件的支持。这将是我们这里的主要数据源。 MS SQL Server
既不能导入也不能导出 CSV。
MS SQL Server
静默截断文本字段。MS SQL Server
的文本编码处理出错。
MS SQL 服务器抛出一条错误消息,因为它不理解引号或转义。 有关该比较的更多信息,请参阅文章 PostgreSQL vs. MS SQL Server.
PostgreSQL
这个数据库是一个成熟的产品,也是久经考验的。我从其他人那里听到了很多积极的反馈(当然,也有一些权衡)。它具有更经典的 SQL 语法,良好的 CSV 支持,而且它是开源的。
值得一提的是SSMS is a way better than PGAdmin. SSMS has an autocomplete feature, multiple results (when you run several queries and get the several results at one, but in PGAdmin你只能得到最后一个)。
无论如何,我现在正在使用 JetBrains 的 DataGrip。
处理工具
我查看了 Spring 批次 和 Apache Spark。 Spring Batch 对于这个任务来说有点太低级了,而且 Apache Spark 提供了更容易扩展的能力,如果将来需要的话。无论如何,Spring Batch 也可以完成这项工作。
关于Apache Spark示例,代码可以在learning-spark项目中找到。 我现在的选择是Apache Spark。