Оптимизация производительности Magento 2
Magento 2 — тяжёлая платформа: стандартная установка делает 200–400 SQL-запросов и 50–100 файловых операций на страницу. Без специальной настройки это даёт TTFB 3–8 секунд на среднем сервере. Задача оптимизации — сократить это до 200–500ms через правильный стек кэширования, конфигурацию PHP и устранение узких мест в запросах.
Стек для production
Целевая архитектура:
CDN (Cloudflare/Fastly) → Varnish → Nginx → PHP-FPM 8.2 → MySQL 8.0
↕ ↕
Redis (cache) Redis (session)
Elasticsearch (catalog search)
Каждый слой критичен. Varnish даёт hit rate 85–95% для анонимных пользователей. Redis убирает дисковые операции на кэш. Elasticsearch заменяет медленный MySQL-поиск по каталогу.
PHP 8.2 + OPcache + JIT
Magento 2.4.6+ официально поддерживает PHP 8.2. Переход с 7.4 даёт прирост 15–25% на CPU-bound операциях.
; /etc/php/8.2/fpm/conf.d/opcache.ini
opcache.enable=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=60000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.fast_shutdown=1
opcache.enable_cli=1
; JIT — даёт 10-20% на вычислительных задачах Magento
opcache.jit=tracing
opcache.jit_buffer_size=256M
PHP-FPM pool:
[magento]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm-magento.sock
listen.backlog = 65535
pm = dynamic
pm.max_children = 40
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 2000
php_admin_value[memory_limit] = 768M
php_admin_value[max_execution_time] = 600
php_admin_value[opcache.file_cache] = /tmp/opcache
Режим production и деплой
# Переключение в production mode
bin/magento deploy:mode:set production
# DI compilation — генерирует интерцепторы, убирает overhead рефлексии
bin/magento setup:di:compile
# Деплой статики с минификацией
bin/magento setup:static-content:deploy ru_RU en_US -j 4
# Сброс и прогрев кэша
bin/magento cache:clean && bin/magento cache:flush
В developer режиме Magento пересоздаёт DI на каждый запрос — разница с production режимом 5–10x по скорости.
MySQL 8.0 — настройка InnoDB
[mysqld]
# InnoDB buffer pool — 70% RAM сервера
innodb_buffer_pool_size = 8G
innodb_buffer_pool_instances = 8
# Redo log
innodb_log_file_size = 1G
innodb_log_buffer_size = 64M
# Flush
innodb_flush_log_at_trx_commit = 2 # 1 = safe, 2 = faster (теряем 1 сек транзакций при краше)
innodb_flush_method = O_DIRECT
# Параллелизм
innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_thread_concurrency = 0
# Запросы
query_cache_type = 0 # Query cache отключить — мьютекс убивает параллелизм
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
Elasticsearch для поиска
MySQL-поиск в Magento 2 (LIKE '%query%') неприемлем для каталогов 10 000+ SKU. Elasticsearch даёт полнотекстовый поиск с релевантностью, автодополнение, фасетную фильтрацию.
# Установка Elasticsearch 8.x
apt install elasticsearch
# Конфигурация Magento
bin/magento config:set catalog/search/engine elasticsearch7
bin/magento config:set catalog/search/elasticsearch7_server_hostname localhost
bin/magento config:set catalog/search/elasticsearch7_server_port 9200
bin/magento config:set catalog/search/elasticsearch7_index_prefix magento2
# Переиндексация
bin/magento indexer:reindex catalogsearch_fulltext
После переиндексации страница поиска с 50 000 товаров отвечает за 50–150ms вместо 2–5 секунд.
Индексирование и крон
Magento 2 имеет индексеры, которые пересчитываются при изменении данных. Для больших каталогов переводим в schedule режим:
# Показать текущий режим
bin/magento indexer:show-mode
# Перевести все индексеры в schedule (обновление по крону)
bin/magento indexer:set-mode schedule
# Запуск крона (если нет системного задания)
bin/magento cron:install
bin/magento cron:run
Проверка состояния индексеров:
bin/magento indexer:status
# catalog_category_product: Ready (за последнюю индексацию: 1.2s)
# catalogsearch_fulltext: Ready (за последнюю индексацию: 45.3s)
Если индексер catalog_product_price работает дольше 5 минут — проблема с объёмом данных или catalog_rule.
Flat catalog
Для каталогов без сложной атрибутики Flat Tables ускоряют выборку:
bin/magento config:set catalog/frontend/flat_catalog_category 1
bin/magento config:set catalog/frontend/flat_catalog_product 1
bin/magento indexer:reindex catalog_category_flat catalog_product_flat
Flat catalog не совместим с некоторыми расширениями — проверять после включения.
Устранение N+1 проблем
Диагностика через n98-magerun2:
# Установка
composer global require n98/magerun2
# Профилирование запросов на странице
n98-magerun2 dev:query-log:enable
# Открываем страницу в браузере
n98-magerun2 dev:query-log:disable
# Анализируем var/debug/db.log
grep -c "SELECT" var/debug/db.log
Типичные источники N+1 в Magento 2:
-
afterLoadплагины, делающие запросы для каждой записи коллекции - атрибуты EAV без
addAttributeToSelectв коллекции - блоки, вызывающие
$product->load($id)вместо работы с коллекцией
Правильный паттерн загрузки коллекции:
$collection = $this->productCollectionFactory->create();
$collection->addAttributeToSelect(['name', 'price', 'status'])
->addFieldToFilter('status', 1)
->addFieldToFilter('visibility', ['in' => [2, 3, 4]])
->setPageSize(24)
->setCurPage(1);
// Один запрос вместо 24+1
CDN для статики
# Настройка base URL для статики через CDN
bin/magento config:set web/unsecure/base_static_url https://cdn.myshop.ru/pub/static/
bin/magento config:set web/secure/base_static_url https://cdn.myshop.ru/pub/static/
bin/magento config:set web/unsecure/base_media_url https://cdn.myshop.ru/pub/media/
bin/magento config:set web/secure/base_media_url https://cdn.myshop.ru/pub/media/
bin/magento cache:flush
Статика и медиа отдаются с CDN-серверов ближайших к пользователю — снижение времени загрузки страницы на 30–50% для удалённых регионов.
Минификация и бандлинг JS/CSS
# Merging CSS/JS
bin/magento config:set dev/css/merge_css_files 1
bin/magento config:set dev/js/merge_files 1
# Минификация
bin/magento config:set dev/css/minify_files 1
bin/magento config:set dev/js/minify_files 1
# JS bundling (уменьшает количество HTTP-запросов)
bin/magento config:set dev/js/enable_js_bundling 1
Critical JS path — requirejs-config.js и default.js загружаются синхронно. Для улучшения FCP используем defer для некритичных модулей через кастомный default_head_blocks.xml.
Замер результата
# До оптимизации
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
https://myshop.ru/catalog/category/view/id/5
# После — типичный результат для правильно настроенного Magento 2
# TTFB: 0.18s (страница из Varnish)
# TTFB: 0.45s (PHP miss, Redis cache hit)
Сроки работ
Настройка PHP 8.2, OPcache, FPM pool, production mode, DI compile, статика: 1 день. MySQL tuning, Elasticsearch, flat catalog: 1–2 дня. Varnish + Redis (кэш + сессии): 2 дня (см. отдельные страницы). Аудит N+1, индексеры, CDN: 2–3 дня. Итого полная оптимизация: 6–10 рабочих дней.







