如何使用laravel处理mysql中的大型更新查询

时间:2017-05-09 19:22:46

标签: php mysql laravel file

有一种方法可以在查询中更新100k记录,mysql数据库可以顺​​利运行吗?

假设有一个表用户包含数十万条记录,我必须更新大约五万条记录,而对于更新,我有这些记录的ID意味着存储在csv文件中的大约五万条记录,

1 - 由于查询的大小太大,查询是否正常?或者如果有任何方法可以放入较小的块,请告诉我?

2-考虑laravel框架,如果有任何选项读取文件的一部分而不是整个文件,以避免内存泄漏,因为我不想同时阅读所有文件,请建议。

欢迎任何建议!

2 个答案:

答案 0 :(得分:4)

如果您正考虑构建UPDATE users SET column = 'value' WHERE id = 1 OR id = 2 OR id = 3 ... OR id = 50000WHERE id IN (1, 2, 3, ..., 50000)之类的查询,那么这可能会太大。如果你可以用一些逻辑来总结它,它会缩短查询速度并加快MySQL的速度。也许你可以做到WHERE id >= 1 AND id <= 50000

如果这不是一个选项,你可以突然发现。您可能会循环遍历CSV文件的行,将查询构建为大WHERE id = 1 OR id = 2...个查询,并且每100行左右(如果仍然太大则为50行),运行查询并为接下来的50个ID开始一个新的。

或者您可以在数据库上运行50.000个单UPDATE个查询。老实说,如果表正确使用索引,那么在大多数现代Web服务器上运行50.000查询只需要几秒钟。即使是最繁忙的服务器也应该能够在一分钟内完成。

至于以块的形式读取文件,您可以使用PHP的基本文件访问功能:

$file = fopen('/path/to/file.csv', 'r');

// read one line at a time from the file (fgets reads up to the
// next newline character if you don't provide a number of bytes)
while (!feof($file)) {
    $line = fgets($file);

    // or, since it's a CSV file:
    $row = fgetcsv($file);
    // $row is not an array with all the CSV columns

    // do stuff with the line/row
}

// set the file pointer to 60 kb into the file
fseek($file, 60*1024);

// close the file
fclose($file);

这不会将完整文件读入内存。不确定Laravel是否有自己的处理文件的方法,但这是在基本的PHP中如何做到这一点。

答案 1 :(得分:3)

根据您需要更新的数据,我建议几点:

  • 如果所有用户都按相同的价值更新 - 正如@rickdenhaan所说,
    您可以从csv每隔X行构建多个批次。
  • 如果必须使用唯一值更新每个用户,则必须运行单个查询。
  • 如果任何更新的列具有索引 - 您应该禁用自动提交并手动执行事务以避免在每次更新后重新索引。

为了避免内存泄漏,我的意见与@ rickdenhaan相同。您应该使用fgetcsv

逐行阅读csv

为避免可能的超时,例如,您可以将脚本处理放入laravel队列