【发布时间】:2020-04-22 09:52:22
【问题描述】:
我有一个功能,用户可以上传CSV 文件(列表),以在DB 中存储/更新电子邮件:
//load CSV
$records = file($request->file('list'), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
//prepare for mass insert
foreach ($records as $email) {
$updateOrCreate[] = [
'email' => $email
];
}
DB::beginTransaction();
try {
$toKeep = [];
//run a loop to cjeck if email already exists if not create
foreach ($updateOrCreate as $record) {
$email = List::updateOrCreate([
'email' => $record['email']
], $record);
$toKeep[] = $email->id;
}
//delete all records that where no in new CSV
if (count($toKeep)) {
List::whereNotIn("id", $toKeep)->delete();
}
} catch (Exception $e) {
DB::rollBack();
return response()->json([
'message' => $e->getMessage()
], 422);
}
DB::commit();
这个解决方案很好用,最多几千条记录,如果尝试上传 50k 或更多,速度很慢,我明白为什么很慢(查询每条记录选择/更新或插入):
foreach ($updateOrCreate as $record) {
$email = List::updateOrCreate([
'email' => $record['email']
], $record);
$toKeep[] = $email->id;
}
对于插入,我使用了原始的 pg_copy_from,效果很好且速度很快
$result = pg_copy_from($dbconn, 'lists (email)', $records, ',');
所以我在徘徊是否有类似的检查记录是否不在列表中删除或添加新的,更有效/更快的方式,也许像pg_copy_from。
【问题讨论】:
标签: php sql laravel postgresql