Урок 16: Оптимизация приложения в Yii 2. База данных, кеширование, минификация

В 16-ом уроке мы разберем одну из тем в разработке, это оптимизацию приложений. Даже если ваш код работает корректно, медленная скорость загрузки страниц или высокие нагрузки на сервер могут испортить впечатление пользователей. В этом уроке я расскажу, как улучшить производительность Yii 2-приложений, используя проверенные методы.

Оптимизация запросов к базе данных

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

Проблема N+1

Частая ошибка новичков, это проблема N+1. Представьте, что вы получаете список статей (SELECT * FROM articles), а затем для каждой статьи отдельно запрашиваете автора:

php
$articles = Article::find()->all();
foreach ($articles as $article) {
    $author = $article->author; // Отдельный запрос для каждой статьи!
}

Если статей 100, это 100 дополнительных запросов. Решение, жадная загрузка данных с помощью метода with():

php
$articles = Article::find()->with('author')->all(); // Все авторы загружаются одним запросом

Использование индексов

Убедитесь, что в таблицах есть индексы на часто используемые поля. Например, для внешних ключей:

sql
CREATE INDEX idx_author_id ON articles(author_id);

В Yii 2 вы можете добавить индексы через миграции:

php
$this->createIndex('idx_author_id', 'articles', 'author_id');

Оптимизация сложных запросов

Используйте методы ActiveQuery для построения эффективных запросов. Например, select() для выбора только нужных полей:

php
$articles = Article::find()
    ->select(['id', 'title', 'created_at'])
    ->where(['status' => 'published'])
    ->all();

Практическая задача:

  1. Найдите в своем коде места с проблемой N+1 и исправьте их, используя with().
  2. Добавьте индексы для полей, которые участвуют в условиях WHERE или JOIN.

Использование ленивой и жадной загрузки

В Yii 2 есть два подхода к загрузке связанных данных: ленивая (lazy) и жадная (eager).

Ленивая загрузка

Ленивая загрузка происходит «по требованию»:

php
$article = Article::findOne(1);
$author = $article->author; // Отдельный запрос выполняется здесь

Это удобно, но может привести к проблеме N+1.

Жадная загрузка

Жадная загрузка предварительно загружает все связанные данные:

php
$articles = Article::find()->with(['author', 'comments'])->all();

Yii 2 выполнит всего три запроса:

  1. Получить статьи.
  2. Получить авторов статей (WHERE IN).
  3. Получить комментарии к статьям (WHERE IN).

Пример с вложенными связями:

php
$articles = Article::find()->with([
    'author.profile', // Загрузить автора и его профиль
    'comments.user'
])->all();

Практическая задача:

  1. Перепишите свой код, заменив ленивую загрузку на жадную там, где это уместно.
  2. Проверьте количество запросов в Debug Toolbar до и после изменений.

Минификация CSS и JS

Сжатие ресурсов уменьшает их размер и ускоряет загрузку страниц.

Настройка AssetManager

В Yii 2 можно настроить автоматическую минификацию через компонент assetManager в config/web.php:

php
'assetManager' => [
    'bundles' => [
        'yii\web\JqueryAsset' => [
            'js' => [
                YII_ENV_PROD ? 'jquery.min.js' : 'jquery.js'
            ]
        ],
    ],
    'appendTimestamp' => true,
    'linkAssets' => true,
],

Использование консольных команд

Для минификации можно использовать утилиты вроде UglifyJS или CSSNano.
Например, добавить задачу в Gruntfile.js:

javascript
uglify: {
    options: { compress: {} },
    target: {
        files: {
            'web/js/all.min.js': ['src/js/*.js']
        }
    }
}

Практическая задача:

  1. Настройте assetManager для сжатия CSS и JS.
  2. Объедините и минифицируйте свои ресурсы с помощью Grunt/Gulp.

Настройка HTTP-кеширования

Кеширование на стороне клиента или сервера сокращает время обработки повторных запросов.

Кеширование в Action

Используйте фильтр yii\filters\HttpCache:

php
public function behaviors() {
    return [
        [
            'class' => 'yii\filters\HttpCache',
            'only' => ['view'],
            'lastModified' => function ($action, $params) {
                return Article::find()->max('updated_at');
            },
        ],
    ];
}

ETag и Last-Modified

Yii 2 автоматически обрабатывает заголовки ETag и Last-Modified, если они заданы:

php
public function actionView($id) {
    $model = Article::findOne($id);
    $response = Yii::$app->response;
    $response->getHeaders()
        ->set('Last-Modified', gmdate('D, d M Y H:i:s', $model->updated_at) . ' GMT');
    return $this->render('view', ['model' => $model]);
}

Практическая задача:

  1. Добавьте HTTP-кеширование для страницы просмотра статьи.
  2. Проверьте заголовки ответа в браузере (вкладка Network).

Заключение

Оптимизация это не разовое действие, а постоянный процесс. Начните с анализа самых «тяжелых» мест через Debug Toolbar, настройте кеширование и следите за количеством запросов. Не забывайте применять полученные знания на практике. Если что-то не получается, пишите в комментариях, помогу.

← Вернуться к полному курсу по Yii 2 для начинающих

Поделиться статьей:
Поддержать автора блога

Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.

Персональные рекомендации
Оставить комментарий