优化数据库查询以避免内存问题
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]);
希望对您有所帮助。
我有一个庞大的用户 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]);
希望对您有所帮助。