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

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

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

Начать курс

Введение: Почему скорость имеет значение?

Представьте, что ваш сайт загружается дольше 3 секунд. По данным Google, 53% пользователей покинут его, а конверсия упадет на 20%. Для PHP-разработчика умение оптимизировать приложение — это не просто «хороший тон», а необходимость. Даже если вы только начинаете свой путь, базовые техники ускорения кода помогут вам создавать быстрые и отзывчивые проекты.

В этой статье мы разберем 4 ключевых направления: от кэширования и работы с базами данных до настройки сервера и профилирования. Вы получите готовые примеры кода и чек-лист для внедрения.

1. Кэширование: сохраняем результат, а не пересчитываем заново

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

1.1. Кэширование в памяти (Memcached / Redis)

Для данных, которые редко меняются (например, список категорий или настройки), идеально подходит кэширование в оперативной памяти.

<?php
// Пример с Memcached
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);

$key = 'categories_list';
$categories = $memcached->get($key);

if ($categories === false) {
    // Данных нет в кэше — получаем из БД
    $categories = $db->query("SELECT * FROM categories")->fetchAll();
    // Сохраняем на 1 час (3600 секунд)
    $memcached->set($key, $categories, 3600);
}

// Используем $categories
foreach ($categories as $cat) {
    echo $cat['name'];
}
?>

1.2. Кэширование HTML-фрагментов (Output Buffer)

Если у вас есть тяжелые блоки (виджеты, меню), кэшируйте готовый HTML.

<?php
function getCachedWidget($widgetName, $ttl = 300) {
    $cacheFile = __DIR__ . '/cache/' . md5($widgetName) . '.html';
    
    if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $ttl) {
        return file_get_contents($cacheFile);
    }
    
    ob_start();
    // Здесь код, который генерирует виджет
    echo "<div class='widget'>Сложный контент...</div>";
    
    $html = ob_get_clean();
    file_put_contents($cacheFile, $html);
    
    return $html;
}

echo getCachedWidget('sidebar_menu');
?>

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

Самое узкое место в PHP-приложениях — это база данных. Один плохой запрос может «убить» производительность всего сайта.

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

Без индекса MySQL вынужден сканировать всю таблицу. Добавьте индексы на поля, которые участвуют в WHERE, JOIN и ORDER BY.

-- Плохо: полное сканирование
SELECT * FROM users WHERE email = 'test@test.com';

-- Хорошо: используем индекс
CREATE INDEX idx_email ON users(email);
SELECT * FROM users WHERE email = 'test@test.com';

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

Это классическая ошибка: в цикле вы дергаете БД для каждого элемента.

<?php
// ПЛОХО: N+1 запросов
$users = $db->query("SELECT * FROM users")->fetchAll();
foreach ($users as $user) {
    $orders = $db->query("SELECT * FROM orders WHERE user_id = " . $user['id']);
    // ...
}

// ХОРОШО: один запрос с JOIN
$users = $db->query("
    SELECT u.*, o.* 
    FROM users u 
    LEFT JOIN orders o ON u.id = o.user_id
")->fetchAll();
?>

2.3. Ленивая загрузка (Lazy Loading)

Не загружайте данные, которые не нужны прямо сейчас. Используйте пагинацию или LIMIT.

// Вместо:
$all = $db->query("SELECT * FROM logs"); // 100 000 строк

// Используйте:
$page = $_GET['page'] ?? 1;
$limit = 20;
$offset = ($page - 1) * $limit;
$logs = $db->query("SELECT * FROM logs LIMIT $limit OFFSET $offset");

3. Настройка сервера и OPcache

Иногда проблема не в коде, а в конфигурации PHP. Самая мощная оптимизация — включить OPcache.

3.1. Включаем OPcache

OPcache кэширует скомпилированный байт-код PHP, избавляя сервер от повторной компиляции скриптов при каждом запросе.

; В php.ini или .user.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
; Отключаем проверку изменений на продакшене (для разработки оставьте 0)
opcache.validate_timestamps=0

После включения вы заметите прирост скорости на 20-40% без изменения кода.

3.2. Настройка сессий

Если сессии хранятся в файлах, а у вас много посетителей, используйте Redis или Memcached для хранения сессий.

// В php.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

4. Профилирование: находим узкие места

Не оптимизируйте вслепую. Используйте инструменты, чтобы понять, что именно тормозит.

4.1. Xdebug + Webgrind

Xdebug генерирует профилировочные файлы, а Webgrind визуализирует их.

// Установка Xdebug (пример для Ubuntu)
sudo apt install php-xdebug

// Включите профилирование в php.ini
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = /tmp

4.2. Простой таймер своими руками

Для быстрой проверки одного участка кода:

<?php
$start = microtime(true);

// Ваш код
for ($i = 0; $i < 100000; $i++) {
    $arr[] = $i;
}                

Блоги

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