Laravel Eloquent take() 在大型数据集中非常慢或内存耗尽

Laravel Eloquent take() is very slow or memory exhausted in large dataset

我有一个多对多关系:

class Game extends Model
{
    public function players()
    {
        return $this->belongsToMany('App\Player');
    }
}
class Player extends Model
{
    public function games()
    {
        return $this->belongsToMany('App\PlayerGame');
    }
}

我有 500k+ game_player 个条目,已创建外键。

当我运行用limit=10时,需要很长时间才能得到结果甚至内存耗尽:

if ($request->filled('limit') && $request->limit > 0) {
    return response(Game::findOrFail($id)->players->take($request->limit), 200);
} else {
    return response(Game::findOrFail($id)->players, 200);
}

我应该改用 SQL 限制吗?我应该怎么做才好呢?

您正在向数据库询问所有相关记录,然后在 PHP 端过滤它们,将它们全部加载到内存中。由于您只需要某些记录,因此您应该向数据库询问这些记录:

Game::findOrFail($id)->players()->take($request->limit)->get()

这将使用关系方法查询数据库并且只取有限的记录集。使用动态 属性 $game->players 时,您正在将整个关系加载到集合中。

如果您要检索大量数据,您可以使用 2 种方法迭代结果:

  1. Chunking
  2. Cursors