背景
加载时包含许多连接、选择和诸如此类的原始 SQL 查询
$results = DB::SELECT($query)
创建了约 500mb、450,000 个项目
$results
集合,这不好。
解决方案
因此 $query 现在改为创建一个临时表,可以通过以下方式读取该临时表:
$new_rows = true;
$chunk = 25000;
$offset = 0;
while ($new_rows) {
$chunked_results = DB::SELECT('SELECT * FROM tmp_table ORDER BY id DESC LIMIT ' . $chunk . ' OFFSET ' . $offset );
if (count($chunked_results) === 0) {
$new_rows = false;
}
foreach ($chunked_results as $row) {
//Do stuff with $row
}
$offset+= $chunk;
unset($chunked_results);
}
问题
尽管在每次查询后取消设置
$chunked_results
,我的脚本仍然在第 75,000 行左右耗尽内存 - 几乎相同。加载的行数没有分块/tmp_table。
这让我相信,不知何故,之前
$chunked_results
的内容保留在内存中,并且不会真正取消设置,或者 DB::class
会记住后台的内容。
执行
DB::RECONNECT('mysql')
会消灭临时表:(
OFFSET
变得越来越慢。 这是因为查询必须跳过越来越多的行。
相反,“在
WHERE
的帮助下记住你离开的地方。” 讨论:https://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks就您而言,WHERE id > $the_last_id_of_prev_query
听起来很合适。
我不建议使用大于 1000 行的块,因为您可能会遇到其他限制。 (>1000 就进入“收益递减”状态。)