我创建了一个从 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/