[英]What is the best way to process large CSV files?
我有一个第三方系统,每天生成大量数据(这些是存储在FTP上的CSV
文件)。 正在生成3种类型的文件:
2 Mb
) 200 - 300 Mb
) CSV
文件约为1 Gb
) 总体而言,4 CSV
的大小为1.5 Gb
。 但是我们应该考虑到每15分钟生成一些文件。 这些数据也应该汇总(不是那么难的过程,但肯定需要时间)。 我需要快速回复。 我正在考虑如何将这些数据和整体存储在实现上。
我们有java
堆栈。 该数据库是MS SQL Standard
。 根据我的测量结果, MS SQL Standard
与其他应用程序无法处理此类负载。 我想到了什么:
MS SQL Enterprise
。 PostgreSQL
。 现在我正在为这种方法开发PoC。 你会在这推荐什么? 可能有更好的选择。
这些大文件是每天的新数据。
您可以考虑查看Apache Spark项目。 验证和策划数据后,可以使用Presto运行查询。
您可以使用uniVocity解析器尽快处理CSV,因为这个库附带了最快的 CSV解析器。 我是这个库的作者,它是开源和免费的(Apache V2许可证)
现在要将数据加载到数据库中,您可以尝试使用univocity框架 (商业)。 我们使用它可以非常快速地将大量数据加载到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();
}
为了提高性能,该框架允许您管理数据库模式并执行诸如删除约束和索引,加载数据以及重新创建数据等操作。 如果需要,还可以很好地支持数据和模式转换。
希望这可以帮助。
好的。 花了一些时间解决这个问题(包括阅读,咨询,试验,做几个PoC)。 我提出了以下解决方案。
数据库 : PostgreSQL
因为它适用于CSV,免费和开源。
工具 : Apache Spark非常适合此类任务。 很好的表现。
关于数据库,决定是一件重要的事情。 选择什么以及将来如何使用这么多数据。 它绝对应该是一个单独的服务器实例,以便不在主数据库实例上生成额外的负载而不阻止其他应用程序。
我在这里考虑过使用Cassandra
,但是这个解决方案现在太复杂了。 Cassandra
没有临时查询。 Cassandra
数据存储层基本上是一个键值存储系统。 这意味着您必须围绕所需的查询“建模”数据,而不是围绕数据本身的结构。
我不想在这里过度工程。 我在这里停止了选择。
这是一种方法,但这里的重大缺点是定价。 很贵。 考虑到我们的硬件,企业版需要花费很多钱。 关于定价,您可以阅读此政策文件 。
这里的另一个缺点是支持CSV文件。 这将是我们的主要数据来源。 MS SQL Server
既不能导入也不能导出CSV。
MS SQL Server
静默方式截断文本字段。
MS SQL Server
的文本编码处理出错。
MS SQL Server抛出错误消息,因为它不理解引用或转义。 有关该比较的更多信息可以在文章PostgreSQL与MS SQL Server中找到 。
这个数据库是一个成熟的产品,也经过了很好的战斗测试。 我从其他人那里听到了很多积极的反馈(当然,还有一些权衡)。 它具有更经典的SQL语法,良好的CSV支持,而且它是开源的。
值得一提的是, SSMS比PGAdmin更好。 SSMS具有自动完成功能,具有多个结果(当您运行多个查询并在一个查询中获得多个结果时,但在PGAdmin中您只获得最后一个结果)。
无论如何,现在我正在使用JetBrains的DataGrip 。
我查看了Spring Batch和Apache Spark 。 Spring Batch对于此任务来说有点太低级了,而且如果将来需要它, Apache Spark还提供了更容易扩展的能力。 无论如何, Spring Batch也可以做这项工作。
关于Apache Spark示例,代码可以在learning-spark项目中找到。 我现在选择的是Apache Spark 。
Pentaho数据集成(或类似的ETL工具)可以处理将数据导入SQL数据库,并可以即时进行聚合。 PDI具有社区版本,可以独立运行或通过Java API运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.