我有一个巨大的Users表(可能有4百万行左右),我想每月运行一次Job,以检查他们的上次登录日期,以及他们是否尚未登录update user并将isPassive列更新为true。
$users = \DB::table('users')
->whereNull('isPassive')->get();
foreach($users as $user)
{
if(!$user->wasActive())
{
$this_user = (new User)::where('id', $user->id)->first();
$this_user->isPassive = true;
$this_user->save();
}
}
我已经学会了使用Laravel来运行作业,但这给了我内存问题。好了,我可以增加服务器的内存,但是根据我在这里所读到的内容,增加内存并不总是最好的解决方案。
我尝试了chunk results,但是当我使用where()
时,它就挂了。如果我在没有和条件的情况下使用它,则效果很好。
我想知道有经验的开发人员将如何中断这项工作以使用更少的内存?
将其命名为Laravel,但这是任何新程序员在学习更好地管理内存时可能会遇到的问题。
谢谢您的建议
答案 0 :(得分:0)
您的代码存在一些问题。首先:
$this_user = (new User)::where(...)->first();
...
此行在foreach
循环的每次迭代中都运行一个新查询,因此实际上您在运行400万个其他不必要的查询。该查询是多余的,因为您已经拥有$user
,并且$this_user
将会是同一件事。更改您的代码,如下所示:
$users = User::whereNull('isPassive')->get();
foreach($users AS $user){
if(!$user->wasActive()){
$user->isPassive = true;
$user->save();
}
}
这样,您将查询减少了一半。
此外,我不确定wasActive()
方法的作用,但是如果您可以将该逻辑移到初始查询中,则可以运行单个update
语句来删除循环:
DB::table("users")
->whereNull("isPassive")
->where(...) // Apply logic from User wasActive() check
->update(["isPassive" => true]);
希望有帮助。