5 способов оптимизировать запросы Laravel

Рассмотрим 5 способов как можно значительно ускорить запросы в базу данных вашего проекта на Laravel. Поговорим только о работе Eloquent и Laravel, без основ оптимизации самой таблицы базы данных (индексы, внешние ключи, типы полей…).

1. Используйте Eager loading (жадную загрузку)

При доступе к отношениям Eloquent как к свойствам, связанные модели загружаются «отложенно». Это означает, что данные отношения фактически не загружаются, пока вы впервые не затребуете доступ к свойству. Однако Eloquent может «жадно» загрузить отношения во время запроса родительской модели. Жадная загрузка позволяет избежать проблем «N+1» с запросами. Жадная (edger) загрузка может сократить количество выполняемых запросов за счет предварительной загрузки связанных моделей. Более подробно мы рассказываем здесь.

// Плохой пример (без жадной загрузки)
// Будет выполнен 101 запрос для 100 постов
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name;
}

// Хороший пример (с жадной загрузкой)
// Будет выполнено 2 запроса для 100 постов
$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name;
}

2. Кэшируйте запросы

Кэширование часто используемых данных может значительно снизить нагрузку на базу данных.

$posts = Cache::remember('posts', 60, function () {
    return Post::all();
});

3. Используйте чанки для большого количества данных или больших таблиц

Разделение на чанки (chunk) позволяет обрабатывать большие наборы данных более мелкими фрагментами, предотвращая переполнение памяти.

Post::chunk(100, function ($posts) {
    foreach ($posts as $post) {
        // ...
    }
});

4. Используйте Eloquent, а не query builder и сырые запросы

Eloquent позволяет писать максимально читаемый код, а изменять функционал приложения с ним несоизмеримо легче. Пишите запросы через функционал Eloquent и перестаньте использовать сырые запросы или конструктор запросов (query builder).

Плохой пример:

SELECT *
FROM `articles`
WHERE EXISTS (SELECT *
              FROM `users`
              WHERE `articles`.`user_id` = `users`.`id`
              AND EXISTS (SELECT *
                          FROM `profiles`
                          WHERE `profiles`.`user_id` = `users`.`id`) 
              AND `users`.`deleted_at` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC

Хороший пример:

Article::has('user.profile')->verified()->latest()->get();

5. Настройка строгости Eloquent

Laravel предоставляет несколько методов, которые позволяют настраивать поведение Eloquent и «строгость» в различных ситуациях. Метод preventLazyLoading принимает необязательный булевый аргумент, указывающий, следует ли запретить отложенную загрузку (lazy loading).

Например, вы можете решить отключить отложенную загрузку только в не-продакшн средах, чтобы ваша продакшн среда продолжала функционировать нормально, даже если отложенная загрузка отношения случайно присутствует в рабочем коде. Обычно этот метод следует вызывать в методе boot сервис-провайдера (AppServiceProvider) вашего приложения:

// AppServiceProvider.php

use Illuminate\Database\Eloquent\Model;

public function boot(): void
{
    Model::preventLazyLoading(!$this->app->isProduction());
}
Запись опубликована в рубрике Laravel с метками , , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий