Laravel中chunk方法分塊處理數(shù)據(jù)

在一些情況下,我們需要對大批量的數(shù)據(jù)進行操作,如果這個時候我們使用foreach的話,很可能會遇到操作超時的情況。
Laravel框架中我們可以很方便的使用chunk方法來解決。

來看一個簡單的例子:

$users = User::all();
foreach ($users as $user) {
  $some_value = ($user->some_field > 0) ? 1 : 0;
  // 一些其他的邏輯
  $user->update(['some_other_field' => $some_value]);
}

這段代碼看起來并沒有什么不對,但是當(dāng)數(shù)據(jù)量很大的時候,情況就不那么樂觀了,一方面是運行時間,再者要考慮數(shù)據(jù)存儲時內(nèi)存消耗完。

在Laravel中,應(yīng)用chunk將數(shù)據(jù)分塊的方法,可以很好的處理這種問題,下面是應(yīng)用chunk的代碼:

User::chunk(100, function ($users) {
  foreach ($users as $user) {
    $some_value = ($user->some_field > 0) ? 1 : 0;
    // might be more logic here
    $user->update(['some_other_field' => $some_value]);
  }
});

這段代碼是執(zhí)行一個100條的數(shù)據(jù)進行更新,當(dāng)執(zhí)行完成后繼續(xù)后面的另一百條數(shù)據(jù)……
也就是說他每次操作的是一個數(shù)據(jù)塊而不是整個數(shù)據(jù)庫。

User::chunk(100, function ($users) {
  foreach ($users as $user) {
    $some_value = ($user->some_field > 0) ? 1 : 0;
    // might be more logic here
    $user->update(['some_other_field' => $some_value]);
  }
});

需要注意的是:當(dāng)使用帶篩選的條件的chunk時,如果是自更新,那么你會漏掉一些數(shù)據(jù),接著看代碼:

User::where('approved', 0)->chunk(100, function ($users) {
  foreach ($users as $user) {
    $user->update(['approved' => 1]);
  }
});

如果要運行上面的代碼,并不會有報錯,但是where條件是篩選approved0user然后將approved的值跟新為1。
在這個過程中,檔第一數(shù)據(jù)庫的數(shù)據(jù)被修改后,下一個數(shù)據(jù)塊的數(shù)據(jù)將是在被修改后的數(shù)據(jù)中選出來的,這個時候數(shù)據(jù)變了,而page也加了1。所以執(zhí)行結(jié)束后,只對數(shù)據(jù)中一半的數(shù)據(jù)進行了更新操作。

如果沒有明白的話,我們來看一下chunk的底層實現(xiàn)。還以上面的代碼為例,假如一共有400條數(shù)據(jù),數(shù)據(jù)被按照100條進行分塊處理。

page = 1: 最開始的時候page為1,選取1-100條數(shù)據(jù)進行處理;

page = 2: 這時候前一百數(shù)據(jù)的approved值全部為1,那么在次篩選的時候數(shù)據(jù)將從第101條開始,而這個時候的page=2,那么處理的數(shù)據(jù)將是第200-300之前的數(shù)據(jù)

之后依舊。

public function chunk($count, callable $callback)
{
    $results = $this->forPage($page = 1, $count)->get();

    while (count($results) > 0) {
        // On each chunk result set, we will pass them to the callback and then let the
        // developer take care of everything within the callback, which allows us to
        // keep the memory low for spinning through large result sets for working.
        if (call_user_func($callback, $results) === false) {
            return false;
        }

        $page++;

        $results = $this->forPage($page, $count)->get();
    }

    return true;
}

原文參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容