Оптимізація продуктивності 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
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 робочих днів.







