1.常规使用
如果有一个这样的需求:对数据库的全部数据查询出来,进行一系列更新
简单粗暴的方法是 把查询到的全部数据,使用foreach
进行操作,然后再存入数据库。
$users = User::all();
foreach ($users as $user) {
$some_value = ($user->some_field > 0) ? 1 : 0;
$user->update(['some_other_field' => $some_value]);
}
如果数据非常宠大,系统可能会耗尽内存,这个方法显然很笨拙。
Laravel
为此提供了一个简洁的解决方案
Laravel
的 chunk
方法可以将集合拆成多个指定大小的小集合
User::chunk(100, function ($users) {
foreach ($users as $user) {
$some_value = ($user->some_field > 0) ? 1 : 0;
$user->update(['some_other_field' => $some_value]);
}
});
以上代码运行的原理是:
- 运行一个
chunk
,这个chunk
查出100个用户数据,对各个用户数据进行更新 - 然后再查看100个用户数据,再执行更新操作,依此类推。
这意味着在查询数据时不会从数据库中获取大量数据,每次查询100条数据,而不是整个表。
这样就减轻的系统的压力。
2.需要注意的地方
本文重点来了:
但是要小心,有过滤结果的不能像这样运行
User::where('approved', 0)->chunk(100, function ($users) {
foreach ($users as $user) {
$user->update(['approved' => 1]);
}
});
从代码执行上讲,这个语句并不会引发任何错误
但是这里的问题是,您要过滤approved=0
的用户,执行approved=1
的数据库操作
然后chunk
下一个100条数据,此时数据已经更改,您将错过一页数据。
这意味着您将只处理一半的条目,还有一半漏掉了。
解决方案:
- 在
Laravel 5.2
之后可以使用chunkById
方法 - 在
Laravel 5.2
之前可以参考以下代码
while(User::where('approved', 0)->count() > 0) {
User::where('approved', 0)->chunk(100, function ($users) {
foreach ($users as $user) {
$user->update(['approved' => 1]);
}
});
}
希望对你有帮助
阿萨德
这么长时间不水一下,突然水一下怎么这么少的😂
😂 水一下就行