Оптимизация производительности PHP приложений: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение

PHP остаётся одним из самых популярных языков для веб-разработки: на нём работают WordPress, Laravel, Symfony и миллионы сайтов. Однако с ростом нагрузки производительность PHP-приложений может стать узким местом. Медленная загрузка страниц не только ухудшает пользовательский опыт, но и снижает позиции в поисковой выдаче (Google учитывает Core Web Vitals).

В этой статье мы разберём проверенные методы оптимизации PHP, которые помогут ускорить ваше приложение без полного переписывания кода. Вы узнаете о кэшировании, настройке интерпретатора, оптимизации базы данных и профилировании.

1. Кэширование: первый шаг к скорости

Кэширование — самый эффективный способ уменьшить время ответа. Вместо того чтобы каждый раз выполнять тяжёлые операции, сохраните результат и отдавайте его из кэша.

1.1. OpCache (PHP 7/8)

PHP — интерпретируемый язык: при каждом запросе он компилирует скрипт в опкод (байт-код). OpCache сохраняет скомпилированный опкод в оперативной памяти, исключая повторную компиляцию. Это даёт прирост производительности до 30–50%.

Как включить: Откройте php.ini и убедитесь, что параметры настроены:

opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2

Для продакшена установите opcache.revalidate_freq=0 и сбрасывайте кэш при деплое вручную.

1.2. Кэширование данных (Redis / Memcached)

Если ваше приложение делает дорогие запросы к БД или внешним API, используйте in-memory хранилища.

Пример с Redis:

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$cacheKey = 'user_profile_' . $userId;
$profile = $redis->get($cacheKey);

if (!$profile) {
    // Дорогой запрос к БД
    $profile = getUserProfileFromDB($userId);
    $redis->setex($cacheKey, 3600, serialize($profile)); // TTL 1 час
}

$profile = unserialize($profile);

1.3. Кэширование HTML (Full Page Cache)

Для статических или редко обновляемых страниц (блог, лендинг) можно кэшировать готовый HTML-вывод. В Laravel это делается через middleware, в Symfony — через HTTP cache.

2. Оптимизация SQL-запросов и базы данных

Чаще всего узким местом PHP-приложения является база данных. Медленные запросы съедают ресурсы сервера.

2.1. Используйте индексы

Убедитесь, что на столбцах, участвующих в WHERE, JOIN и ORDER BY, стоят индексы. Проверить это можно через EXPLAIN SELECT ....

Плохой запрос (без индекса):

SELECT * FROM orders WHERE status = 'pending';

Хороший запрос (с индексом):

CREATE INDEX idx_orders_status ON orders (status);
SELECT * FROM orders WHERE status = 'pending';

2.2. Избегайте N+1 запросов

Это классическая ошибка ORM: в цикле получаем данные для каждой записи.

Проблема (Laravel Eloquent):

$users = User::all();
foreach ($users as $user) {
    echo $user->profile->bio; // каждый раз новый запрос
}

Решение (жадная загрузка):

$users = User::with('profile')->get();
foreach ($users as $user) {
    echo $user->profile->bio; // один запрос
}

2.3. Пагинация вместо LIMIT с большим смещением

При LIMIT 10 OFFSET 100000 MySQL всё равно перебирает 100010 строк. Используйте cursor-based pagination (поиск по индексу):

SELECT * FROM posts WHERE id > $lastId ORDER BY id ASC LIMIT 10;

3. Оптимизация кода и архитектуры

Даже при идеальной БД и кэше плохой код может тормозить приложение.

3.1. Автозагрузка классов (Composer)

Не подключайте файлы вручную через require — используйте PSR-4 автозагрузку от Composer. Это загружает только те классы, которые реально нужны.

// composer.json
{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

После этого выполните composer dump-autoload -o (оптимизированная карта классов).

3.2. Избегайте медленных функций внутри циклов

Функции in_array(), array_search() на больших массивах работают медленно. Замените их на isset($hash[$key]) или array_key_exists().

Медленно:

foreach ($items as $item) {
    if (in_array($item, $largeArray)) { ... }
}

Быстро:

$hash = array_flip($largeArray);
foreach ($items as $item) {
    if (isset($hash[$item])) { ... }
}

3.3. Используйте современные версии PHP

Каждая новая версия PHP (7.4 → 8.0 → 8.2) приносит значительные улучшения производительности. PHP 8.2 работает в среднем на 30% быстрее, чем PHP 7.4, благодаря JIT-компилятору и оптимизации типов.

4. Настройка веб-сервера и окружения

Иногда проблема не в коде, а в конфигурации сервера.

4.1. Используйте PHP-FPM

Вместо старого mod_php (Apache) используйте PHP-FPM — он управляет процессами более эффективно.

Блоги

Рекомендаций по книгам