Оптимизация производительности OpenCart
Стандартная установка OpenCart 3.x/4.x без тюнинга выдаёт TTFB 800–1500ms на средних каталогах. Основные причины: неоптимальные запросы к базе данных, отсутствие опкэша, тяжёлые расширения без кэширования, несжатые ресурсы.
Профилирование: где узкое место
Перед оптимизацией — измерение. Включить логирование медленных запросов MySQL:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Через 30 минут работы сайта анализируем:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
Типичные проблемы OpenCart в slow log:
-
SELECT * FROM oc_product_descriptionбез индекса поlanguage_id -
getProducts()делает N+1 запросов на атрибуты - модули доставки и оплаты делают запросы к внешним API при каждой загрузке корзины
Кэширование OpenCart
OpenCart 3 имеет встроенный файловый кэш в system/storage/cache/. Переключение на Memcached или Redis делается через system/library/cache.php:
// config.php (в корне)
define('CACHE_DRIVER', 'redis');
define('CACHE_PREFIX', 'oc_');
// Для redis:
define('REDIS_HOST', '127.0.0.1');
define('REDIS_PORT', 6379);
define('REDIS_AUTH', '');
define('REDIS_DB', 1);
В OpenCart 4 конфигурация кэша через config/opencart.php в разделе cache:
'cache' => [
'engine' => 'redis',
'expire' => 3600,
'host' => '127.0.0.1',
'port' => 6379,
],
После переключения на Redis время рендера страницы каталога снижается на 40–60% на каталогах от 5000 товаров.
PHP OPcache и FPM
; opcache.ini
opcache.enable=1
opcache.memory_consumption=192
opcache.max_accelerated_files=8000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1
PHP-FPM настройка под OpenCart:
pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 1000
pm.max_requests сбрасывает worker после 1000 запросов — критично для OpenCart, где некоторые расширения накапливают состояние в статических переменных.
Оптимизация базы данных
Индексы, которых нет в стандартной схеме:
-- Ускоряет выборку товаров по категории со статусом
ALTER TABLE oc_product ADD INDEX idx_status (status);
ALTER TABLE oc_product_to_category ADD INDEX idx_category (category_id);
-- Для сортировки по популярности/дате
ALTER TABLE oc_product ADD INDEX idx_date_added (date_added);
-- Атрибуты (частый N+1)
ALTER TABLE oc_product_attribute
ADD INDEX idx_product_lang (product_id, language_id);
Регулярная очистка устаревших сессий:
DELETE FROM oc_session WHERE expire < UNIX_TIMESTAMP(NOW() - INTERVAL 7 DAY);
Добавить в cron раз в сутки.
Nginx-конфигурация для статики и gzip
# Долгое кэширование статики
location ~* \.(jpg|jpeg|png|webp|gif|ico|svg|woff2|css|js)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml image/svg+xml;
gzip_min_length 1024;
# Brotli (если установлен модуль)
brotli on;
brotli_comp_level 5;
brotli_types text/plain text/css application/json application/javascript image/svg+xml;
Тяжёлые расширения
Расширения типа «супер-мега-SEO-пак» часто добавляют 5–15 запросов к базе на каждую страницу. Диагностика:
// Временно добавить в index.php перед require
$start = microtime(true);
register_shutdown_function(function() use ($start) {
error_log('Page time: ' . round((microtime(true) - $start) * 1000) . 'ms');
});
Отключать расширения по одному и сравнивать время — быстрый способ найти виновника.
Изображения
OpenCart не конвертирует изображения в WebP автоматически. Быстрое решение через nginx:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
location /image/ {
try_files $uri$webp_suffix $uri =404;
}
На сервере конвертируем существующие изображения:
find /var/www/opencart/image -name "*.jpg" -o -name "*.png" | \
xargs -P4 -I{} sh -c 'cwebp -q 80 "$1" -o "${1%.*}.webp"' -- {}
Сроки работ
Настройка OPcache, PHP-FPM, Redis-кэша, nginx, индексов БД: 2–3 дня. Аудит расширений и устранение проблемных: 1–2 дня. Конвертация изображений в WebP и настройка nginx для раздачи: 0.5 дня.







