Laravel Eloquent take () работает очень медленно или память исчерпана в большом наборе данных

#mysql #laravel #eloquent #limit #laravel-collection

#mysql #laravel #eloquent #ограничение #laravel-collection

Вопрос:

У меня есть отношения «многие ко многим», поскольку:

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

У меня более 500 тысяч записей game_player, создаются внешние ключи.

Требуется много времени, чтобы получить результат или даже исчерпать память, когда я запускаю это с limit=10 :

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

Должен ли я вместо этого использовать SQL limit? И как мне это сделать красиво?

Ответ №1:

Вы запрашиваете у базы данных все связанные записи, затем фильтруете их на стороне PHP, которая загружает их все в память. Поскольку вам нужны только определенные записи, вы должны запрашивать у базы данных эти записи:

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

Это будет использовать метод отношения для запроса к базе данных и принимать только ограниченный набор записей. При использовании динамического свойства $game->players вы загружаете все отношения в коллекцию.

Комментарии:

1. Спасибо и не знал, что скобки имеют такое большое значение.

Ответ №2:

Если вы извлекаете много данных, вы можете использовать 2 метода для повторения результата:

  1. Фрагментация
  2. Курсоры