php - 仅将不存在的数据从 CSV 导入数据库

标签 php csv doctrine-orm symfony-2.8

我创建了一个从 CSV 文件读取数据的脚本,检查数据是否已存在于数据库中,如果不存在则将其导入。如果数据确实存在(特定产品的代码),则需要从 CSV 文件更新其余信息。

例如; 我的 CSV 文件中有一个代码为 WTW-2LT 的成员,名为 Alex,姓 Johnson。该脚本检查代码为 WTW-2LT、名为 Alex 和姓氏 Johnson 的成员是否已经存在,如果存在,则需要从脚本中更新联系方式和额外详细信息(还需要检查主题和讲师等其他详细信息,所有详细信息都在 CSV 中的一行中),如果它不存在,则必须创建新成员。

我的脚本是我目前拥有的最少其他检查以防止现在分心的内容;

while ($row = fgetcsv($fp, null, ";")) {
    if ($header === null) {
        $header = $row;
        continue;
    }

    $record = array_combine($header, $row);

    $member = $this->em->getRepository(Member::class)->findOneBy([
        'code' =>$record['member_code'],
        'name' =>$record['name'],
        'surname' =>$record['surname'],
    ]);

    if (!$member) {
        $member = new Member();
        $member->setCode($record['member_code']);
        $member->setName($record['name']);
        $member->setName($record['surname']);
    }    
    $member->setContactNumber($record['phone']);
    $member->setAddress($record['address']);
    $member->setEmail($record['email']);

    $subject = $this->em->getRepository(Subject::class)->findOneBy([
        'subject_code' => $record['subj_code']
    ]);

    if (!$subject) {
        $subject = new Subject();
        $subject->setCode($record['subj_code']);
    }
    $subject->setTitle($record['subj_title']);
    $subject->setDescription($record['subj_desc']);
    $subject->setLocation($record['subj_loc']);

    $lecturer = $this->em->getRepository(Lecturer::class)->findOneBy([
        'subject' => $subject,
        'name' => $record['lec_name'],
        'code' => $record['lec_code'],
    ]);

    if (!$lecturer) {
        $lecturer = new Lecturer();
        $lecturer->setSubject($subject);
        $lecturer->setName($record['lec_name']);
        $lecturer->setCode($record['lec_code']);
    }
    $lecturer->setEmail($record['lec_email']);
    $lecturer->setContactNumber($record['lec_phone']);

    $member->setLecturer($lecturer);

    $validationErrors = $this->validator->validate($member);
    if (!count($validationErrors)) {
        $this->em->persist($member);
        $this->em->flush();
    } else {
        // ...
    }
}

您会注意到此脚本必须查询数据库 3 次以检查是否存在一行 CSV。在我的例子中,我有多达 2000 多行的文件,因此对每一行执行 3 次查询以检查该行是否存在是非常耗时的。

不幸的是,我也无法批量导入行,因为如果一个主题不存在,它会创建它很多次,直到该批处理被刷新到数据库,然后我坐在重复的记录中,这些记录毫无意义。

如何最大限度地提高性能和速度?就像首先从数据库中获取所有记录并将其存储在数组中(消耗内存?)然后进行检查并将行添加到数组并从那里检查...

有人可以帮我找到改进方法吗(请提供示例代码?)

最佳答案

老实说,我确实发现 2000 多行的查询量是原来的 3 倍,但并不多。但是,由于您要求的是性能,所以这是我的两分钱:

使用框架总是会产生开销。这意味着如果您使用 native PHP 编写此代码,它将运行得更快。我不熟悉 symfony,但我假设您将数据存储在数据库中。在 MySQL 中,您可以使用命令 INSERT ... ON DUPLICATE KEY update。如果您已将 3 个字段(代码、姓名、姓氏)设置为主键(我假设是这样),您可以使用它来:插入数据,但如果该键已存在,则更新数据库中的值。 MySQL 将为您执行检查,以查看数据是否已更改:如果没有,则不会发生磁盘写入。

我非常确定您可以将 native SQL 写入 symfony,允许您使用框架提供的安全性,同时加快您的插入速度。

关于php - 仅将不存在的数据从 CSV 导入数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45759157/

相关文章:

PHPUnit 和扩展类

php - 直接用 PHP 编写元素的样式是否被认为是不好的做法?

php - 是否可以在 PHP 中声明一个静态和非静态方法?

function - 将属性传递给函数管道输出错误

ruby-on-rails - Ruby 查看 csv 数据

php - 如何在 PHP 中处理超过 100k 行的 CSV?

php - Doctrine2 LEFT JOIN condition1 OR condition2

php - 使用 ZendFramework 2 + Doctrine 2 在分页集合中使用水合器更改对象类型

dependency-injection - Symfony 2 依赖注入(inject)到实体函数中

csv - 将包含带引号的值的表导出到 hive 中的本地 csv