优化数据库查询以避免内存问题

Optimise database query to avoid memory issues

我有一个庞大的用户 table(大约 400 万行),我想 运行 每月检查他们的最后登录日期,如果他们没有登录更新用户和更新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 但这是任何新程序员在学习更好地管理内存时可能会遇到的问题。

感谢任何建议

您的代码存在一些问题。第一:

$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]);

希望对您有所帮助。