提高 Laravel 大量更新的效能

前言

Laravel 的 Eloquent 提供了很方便的方式來進行資料的更新,如果要依據條件更新多筆資料,通常會使用迴圈的方式來進行資料的更新,但如果需要更新大量的資料的話,這樣的用法則很容易產生效能的問題。

一般用法

1
2
3
4
5
6
$orders = Orders::get();
$orders->each(function (Order $order) {
$order->update([
'price' => $order->price + 10
]);
});

為了解決效能問題,需要改變操作方式,組合成原生的 SQL ,一次性地修改資料庫的資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$orders = Orders::get();

foreach ($orders->chunk(5000) as $chunk) {
$cases = [];
$ids = [];
$params = [];

foreach ($chunk as $order) {
$cases[] = "WHEN {$order->id} then ?";
$params[] = $order->price + 10;
$ids[] = $order->id;
}

$ids = implode(',', $ids);
$cases = implode(' ', $cases);

if (!empty($ids)) {
\DB::update("UPDATE transactions SET `price` = CASE `id` {$cases} END WHERE `id` in ({$ids})", $params);
}
}

References
https://dev.to/kodeas/bulk-update-multiple-records-with-separate-data-laravel-4j7k