Запрос Laravel, который является более производительным

#php #laravel #eloquent

Вопрос:

Я довольно новичок в laravel и sql, я заметил, что многого можно достичь с помощью различных методов. Я хочу знать, что более эффективно?

 Message::where('user_id', auth()->user()->id)->get()
 

или

 auth()->user()->messages
 

Кто-то, кого я знаю, предупредил меня о нетерпеливой загрузке, что это сильно влияет на производительность.

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

1. Это не совсем проблема, но упреждающее решение возможной проблемы, с которой я могу столкнуться в будущем. Я создаю приложение для обмена сообщениями, поэтому ожидал, что моя таблица сообщений будет содержать миллионы данных. Я осознаю эффективность всех своих запросов

2. Есть и другие способы написания этих запросов, если вы действительно этого хотите. Беспокойтесь о проблемах с производительностью, если/когда вы с ними столкнетесь. До тех пор используйте любые техники, которые имеют смысл, которые приведут к достижению вашей цели (решению проблем). Я не уверен, почему кто-то сказал бы 'warn' вам о нетерпеливой загрузке, поскольку это решает проблему n 1 запроса при доступе к отношениям, и это хорошо, если только вы не стремитесь загружать и никогда не получаете доступ к отношениям.

3. Я почти уверен, что оба показанных примера приведут к одному и тому же messages запросу.

Ответ №1:

Два предоставленных метода должны выполнять аналогичные запросы к базе данных в фоновом режиме. Один для извлечения пользователя, а другой для извлечения всех сообщений для этого одного пользователя. Особой разницы нет.


Это может стать проблемой, когда вы начнете извлекать вещи внутри цикла. Например:

 $users = User::all();

foreach ($users as $user) {
    // Messages are fetched separately for every single user inside this loop 
    // since the relationship is not present. 
    // Query like: SELECT * FROM messages WHERE user_id = ?
    Log::info($user->messsages); 
}
 

Мы можем решить эту проблему, быстро загрузив все сообщения, выполнив:

 User::with('messages')->all();
 

Таким образом, будет выполнен только один запрос SELECT * FROM messages WHERE user_id IN (?, ?, ?, ?) , и эти сообщения будут сопоставлены с правильными пользователями на стороне PHP. Поэтому, когда вы запускаете цикл foreach, связь уже загружена и никакие дополнительные запросы не выполняются.


В Интернете вы можете найти более подробную информацию об этом, выполнив поиск «Проблема Laravel n 1». Название происходит по той причине, что без активной загрузки в этом сценарии вы выполняете дополнительный ( 1) запрос для каждой отдельной модели. При активной загрузке это можно решить всего за 2 запроса.

Эпизод с ларокастами: Нетерпеливая загрузка