Laravel cursor 造成 Allowed memory size of xxxx bytes exhausted (tried to allocate xxxx bytes)

當使用 Laravel Query Builder 的 cursor 時會造成記憶體不足的問題,網路上雖然查到說可以停掉 MySQL 的 Buffered Query,但實際上設定了之後還是會有記憶體不足的狀況發生。

參考 1:Using Cursor on large number of results causing memory issues
參考 2:Boost Your App’s Performance: Processing Large MySQL Tables with Eloquent ORM

也有人推薦使用 chunk 的方式,但實測過後也是一樣,因為無論如何 MySQL 就是要載入這麼多資料列,因此解題的方向我們朝向減少每一次取得的資料列數量。

這個範例概念是取得最新的 id,並且每次取得一千筆資料做處理,如此一來便能解決載入一次載入大量資料的問題。

$latest_id = DB::table('records')->latests()->first()->id;
$parts = ceil($latest_id / 1000);

for ($i = 0; $i <= $parts; $i++) {
  $records = DB::table('records')->whereIn('id', [$i, $i + 1000])->get();
  // 處理 records
}

閱讀更多:如何設定 PHP memory_limit 來調整效能,避免記憶體不足問題