mql21/csv-importer

用于在Symfony应用程序中导入CSV文件的工具

dev-master 2020-10-03 11:45 UTC

README

ORM(对象关系映射)是操作数据库表的有用工具,通过我们通常所说的“实体”来进行,这些实体最终只是类。这样,我们就可以操作那些类,并将它们持久化到我们的数据库中,而无需编写整个SQL代码。

当然,ORM如Doctrine或Propel非常出色,并且具有优势。然而,当您需要处理大量数据集(例如,通过CSV文件导入大量记录)时,有时它们并不十分有用。Doctrine有批量处理机制,但对于非常大的数据集,处理时间仍然可能相当长。

本项目的主要目标是提供一个解决方案,以尽可能短的时间内导入大型CSV文件。目前,本项目已准备好在Symfony(4.3或更高版本)应用程序中使用,但未来可能也会支持其他PHP框架。

安装

要安装此项目,只需使用Composer要求依赖关系

composer require mql21/csv-importer:dev-master

设置CsvImporter

在使用CsvImporter之前,需要对其进行设置。

首先,您需要允许CsvImporterInterface在您的应用程序中被注入为服务,将以下行添加到services.yaml文件中

mql21\CsvImporter\CsvImporterInterface: ~

现在配置CsvImporter依赖项,添加

mql21\CsvImporter\Builder\CsvImporterMysqlBuilder:
    arguments:
        $csvMappingFields: "%csv_mapping_fields%"

csv_importer.mysql_builder:
    class: mql21\Adapter\CsvImporter\Builder\CsvImporterMysqlBuilder

mql21\CsvImporter\Adapter\CsvImporterMysqlAdapter:
    arguments:
        $csvImporterMysqlBuilder: "@csv_importer.mysql_builder"

csv_importer.mysql_adapter:
    class: mql21\CsvImporter\Adapter\CsvImporterMysqlAdapter

然后,您可以将MySQL适配器简单地自动注入到您的控制器、服务或应用程序中的任何您想要的区域

App\Service\Import\MyImportService:
    arguments:
        $csvImporter: "@csv_importer.mysql_adapter"

使用CsvImporter

CSV数据需要在services.yaml中定义,以便导入器知道CSV与数据库之间的映射。为此,您可以在parameters部分下定义以下配置

parameters:
    csv_mapping_fields:
        test.person: ## database.destination_table_name
            name: ## csv column name
                column_name: 'name' ## database table name
                required: true ## cannot be empty in csv
            surname:
                column_name: 'surname'
                required: true

所有CSV配置都需要在csv_mapping_fields范围内定义。

现在您可以在应用程序中注入CsvImporterInterface并按以下方式执行导入

$csvPath = "some/csv/path/file.csv";
$tableName = "test.person";
$completeMessage = $csvImporter->import($csvPath, $tableName);

提示:确保始终在您的类中注入CsvImporterInterface以遵循依赖倒置原则。

要查看CsvImporter的使用示例,请访问此仓库:https://github.com/miquelp/Csv-Importer-Example

一些有趣的数据

注意:正如您可能已经注意到的,$csvImporter并没有明确声明,因为它是通过DI(依赖注入)注入的。

如下图表清楚地显示,使用Doctrine的EntityManager将实体持久化到数据库中可能需要一些时间,特别是如果我们处理相对较大的数据集时。

Alt text

如您所见,仅写入10000条记录就花费了大约11.5分钟(691.15秒)。

然而,由于CsvImporter使用原生查询写入整个数据,现在所需的时间几乎可以忽略不计。

Alt text

此外,如果我们尝试导入更大的数据集,我们也可以欣赏到导入时间相当低。

Alt text

如我们所见,仅需要大约4.7秒即可导入100万条记录。

旁注:这些数据是从安装在16GB RAM的计算机上的本地MySQL数据库收集的。

进一步的工作和为项目做出贡献

任何关于此项目的反馈、修复或贡献都受欢迎。如果您想做出贡献,请随时提交一个pull请求,它将尽快得到检查。

以下是可以立即完成的待办事项列表

  • 添加对相关表的支持。CsvImporter的设计目的是将数据写入单个表,因此尚未实现关系。添加某种机制以允许写入多个相关表将非常有意思。
  • 添加一些单元测试。
  • 将SRP(单一责任原则)应用于CsvImporterMysqlBuilder.php,通过将验证方法提取到单独的类中。
  • 添加更多字段验证。目前只有两种验证:必填和十进制。任何其他字段验证都将非常受欢迎。
  • 使这个库不依赖于任何特定框架。目前它明确地设计为与Symfony一起工作,但添加对其他框架的支持也将非常有意思。