65 лет полету человека в космос! Хостинг и домены со скидкой
до 22.04.2026 Подробнее
Выберите продукт

Базовый тюнинг MySQL/MariaDB на малом VDS: InnoDB, slow query log и индексы

Как выжать максимум из MySQL/MariaDB на небольшом VDS с 1–2 ГБ ОЗУ. Настроим InnoDB и per‑connection буферы, slow query log, редо‑журналы, индексы и Performance Schema. Пошаговый, безопасный план тюнинга без магии и риска свопа.
Базовый тюнинг MySQL/MariaDB на малом VDS: InnoDB, slow query log и индексы

Если у вас небольшой VDS (1–2 vCPU и 1–2 ГБ ОЗУ), то правильный базовый тюнинг MySQL/MariaDB даёт ощутимый выигрыш без сложных трюков. В этой статье собрал минимально необходимые шаги: понимание ограничений памяти и диска, настройка InnoDB (включая innodb_buffer_pool_size), полезные параметры журнала медленных запросов (slow query log), основы индексации и несколько диагностических приёмов через Performance Schema для осмысленной query optimization. Сразу предупрежу: магии нет. Есть дисциплина измерений и аккуратные изменения по одному за раз.

Ограничения малого VDS и приоритеты

Малый VDS чаще всего упирается в три вещи: память, случайный I/O и «взрывающиеся» по памяти соединения при пиках. Поэтому приоритизируем:

  • максимально возможный буфер InnoDB, чтобы рабочий набор помещался в RAM;
  • ограничение «дорогих» на соединение буферов и числа соединений;
  • видимость проблем: включаем slow query log и делаем короткие циклы анализа-фикса;
  • минимум фич, которые мало дают, но много стоят (например, чрезмерные статистики Performance Schema либо слишком агрессивные per-connection буферы).

Ключевая мысль: сначала обеспечить стабильную память и предсказуемый I/O, затем точечно оптимизировать запросы и индексы. Если текущих ресурсов не хватает даже после тюнинга — планируйте апгрейд на более мощный VDS.

Если думаете о подборе тарифа по CPU/RAM под вашу нагрузку, посмотрите разбор критериев выбора: как выбирать план VDS по CPU, RAM и диску.

Планирование памяти: буферы InnoDB и стоимость соединений

Размеры для innodb_buffer_pool_size

Буферный пул InnoDB — главный потребитель памяти и главный ускоритель чтения/записи. Базовые ориентиры для малых инстансов:

  • 512 МБ RAM: innodb_buffer_pool_size 256–320 МБ.
  • 1 ГБ RAM: 512–700 МБ.
  • 2 ГБ RAM: 1–1.2 ГБ.

Держите запас под сам сервер, системный кеш страницы, binlog (если включён), таблицы Performance Schema, временные таблицы и соединения. Пул лучше чуть меньше идеала, чем риск оверкоммита и свопа.

Per-connection буферы: незаметные убийцы памяти

Каждое соединение может потреблять дополнительные буферы: sort_buffer_size, join_buffer_size, read_buffer_size, read_rnd_buffer_size, а также память под временные таблицы (tmp_table_size/max_heap_table_size). Умножьте их на одновременные соединения — легко получить сотни мегабайт сверх ожиданий.

Базовые рекомендации для малого VDS:

  • max_connections: задайте реальный потолок приложения (например, 50–100), а не «на вырост».
  • sort_buffer_size, join_buffer_size: начните с 1–2 МБ и повышайте точечно, если видите регулярные крупные сортировки/соединения.
  • tmp_table_size и max_heap_table_size: держите равными и умеренно консервативными (например, 32–64 МБ), контролируя метрику Created_tmp_disk_tables.

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

Если проект ещё на виртуальный хостинг, а вам нужен полный контроль над конфигурацией MySQL — переезд на VDS даст свободу тюнинга и предсказуемые ресурсы. Для безпростойного переноса см. практику: миграция сайта без простоя или переезд с виртуального хостинга на VDS.

Схема памяти: буферный пул InnoDB и per-connection буферы

InnoDB: настройки по умолчанию и точечные улучшения

Буферный пул и его инстансы

Помимо innodb_buffer_pool_size, учитывайте innodb_buffer_pool_instances. На малых объёмах RAM достаточно 1 (или 2 при пуле > 1 ГБ). Большое число инстансов на небольшом пуле приводит к избыточной фрагментации и накладным расходам.

Redo-журналы: разница MySQL и MariaDB

Если используете MySQL 8.0+, обратите внимание, что вместо старого innodb_log_file_size применяется innodb_redo_log_capacity (суммарная ёмкость редо-журналов). Для MariaDB по-прежнему актуальны innodb_log_file_size и innodb_log_files_in_group. Слишком маленький редо приведёт к частым flush и I/O-штормам, слишком большой — к долгой аварийной восстановительной фазе.

  • Стартовые значения: MySQL 8.0 — innodb_redo_log_capacity 256–1024 МБ в зависимости от нагрузки записи; MariaDB — 2×256 МБ или 2×512 МБ (innodb_log_file_size × innodb_log_files_in_group).
  • Проверяйте отношение Log Writes к fsync и латентность диска; цель — избежать постоянных принудительных сбросов.

Синхронизация и надёжность: innodb_flush_log_at_trx_commit и сопутствующие

innodb_flush_log_at_trx_commit=1 даёт максимальную надёжность — безопасный дефолт для критичных данных и на серверах с надёжным хранилищем. Значение 2 часто ускоряет вставки/обновления при умеренной потере устойчивости к внезапному отключению питания. 0 обычно не рекомендую на проде. Если используется бинарный лог, учитывайте sync_binlog=1 для сильной консистентности или 0/100 для компромисса.

Метод флеша и смежные опции

innodb_flush_method часто оставляют по умолчанию, но на многих платформах O_DIRECT снижает двойное кэширование (особенно если буферный пул большой). Проверьте поведение в нагрузочных тестах. innodb_doublewrite оставьте включённым для целостности, отключать — только при наличии чётких гарантий на хранилище и осознанного риска. innodb_adaptive_hash_index обычно помогает OLTP-нагрузкам; отключение имеет смысл лишь при наблюдаемом latch-contention.

file-per-table и формат хранения

innodb_file_per_table включён по умолчанию и упрощает управление пространством. Изредка помогает дефрагментация путём OPTIMIZE TABLE отдельных крупных таблиц, но делайте это в тихие часы и после полного бэкапа.

Query Cache

В MySQL 8.0 он удалён. В MariaDB Query Cache всё ещё существует, однако на многопоточном доступе часто вредит из-за глобальных блокировок. На малом VDS со смешанной нагрузкой лучше оставить выключенным.

Slow query log: быстрый поиск медленных мест

Журнал медленных запросов (slow query log) — обязательный инструмент. Он почти бесплатен при разумных порогах и радикально сокращает время поиска «узких горлышек».

Базовые параметры:

  • slow_query_log=ON — включить лог;
  • long_query_time=0.5–1.0 сек для начала;
  • log_queries_not_using_indexes=ON — полезно на этапе аудита, но постоянно не держите;
  • min_examined_row_limit≥1000 — отсечёт «мусор»;
  • log_slow_admin_statements=ON — фиксирует тяжёлые операции обслуживания.

Разбор лога начинайте с агрегирования по «сигнатурам» запросов, а не по конкретным значениям параметров. Цель — найти шаблоны, которые стабильно «жгут» CPU/диск. Дальше — query optimization через индексы, переписывание WHERE/JOIN, уменьшение объёма возвращаемых данных, покрывающие индексы и т.д.

После активного этапа анализа снизьте детализацию slow log, чтобы уменьшить накладные расходы и размер файлов логов.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Performance Schema и sys: диагностика без гадания

Performance Schema по умолчанию включён и даёт массу сигналов: где ожидания (waits), какие объекты «горячие», какие запросы чаще всего самые дорогие по времени/строкам. На малом VDS важно не раздувать потребление памяти — оставьте включённым, но не активируйте все потребители событий без необходимости.

На что смотреть в первую очередь:

  • Общие «узкие места»: ожидания по I/O (таблицы/индексы), mutex/lock contention;
  • Digest топ-стейтментов: шаблоны запросов с наибольшей стоимостью и их распределение;
  • «Горячие» таблицы и индексы: дисбаланс использования, излишние полные сканы.

В паре со slow query log это позволяет быстро сузить поиск и переходить к точным поправкам в индексации или переписыванию запросов.

Анализ slow query log и агрегирование запросов по сигнатурам

Индексы: меньше таблиц-сканов, больше попаданий в память

Правильные индексы — это 80% успеха. InnoDB — B-дерево, поэтому порядок полей в составном индексе критичен.

  • Составные индексы по селективности слева направо: поле с высокой селективностью — ближе к началу. Пример: (status, created_at) для WHERE status=? AND created_at BETWEEN ....
  • Покрывающие индексы: если запрос читает только поля индекса, сервер избегает чтения строк (Extra: Using index).
  • Префиксные индексы на длинных строках: email(64) вместо полного, если селективность приемлема.
  • Функциональные индексы: MySQL 8.0 — выражения и/или генерируемые столбцы; MariaDB — виртуальные/материализованные колонки.
  • FULLTEXT для текстового поиска вместо LIKE с ведущим процентом.
  • Первичный ключ — компактный и монотонный (INT/BIGINT AUTO_INCREMENT), если это согласуется с моделью данных.

Проверяйте планы через EXPLAIN и при возможности EXPLAIN ANALYZE. Признаки Using filesort и Using temporary на больших объёмах — сигнал к пересмотру индекса или переписыванию запроса.

Запросы: маленькие победы без переписывания проекта

  • Избегайте SELECT * в частых путях — выбирайте необходимые столбцы.
  • Фильтруйте до JOIN — переносите селективные условия в подзапросы/CTE слева.
  • Согласуйте ORDER BY с левой частью индекса и направлением.
  • Оптимизируйте пагинацию: вместо OFFSET N LIMIT M при больших N используйте keyset pagination.
  • Разбивайте избыточные OR на UNION ALL, если это улучшает планы.

Транзакции и изоляция

Дефолтная изоляция InnoDB — REPEATABLE READ. Она хороша, но длинные транзакции копят историю (undo) и утяжеляют «чистку». Если приложение допускает, рассмотрите READ COMMITTED — она снижает конкуренцию за версионность. В любом случае:

  • держите транзакции короткими;
  • избегайте «залипших» транзакций в пулах соединений;
  • следите за метриками Innodb_row_lock_time, ростом undo и долгими блокировками.

Временные таблицы и диск

Большая доля «непонятных тормозов» — это внезапный уход во временные таблицы на диске. Контролируйте Created_tmp_disk_tables и Created_tmp_tables, настраивайте tmp_table_size/max_heap_table_size синхронно, чтобы больше временных таблиц оставались в памяти. Но не раздувайте эти значения бездумно — на малом VDS это риск OOM при всплесках соединений.

Файловая система и слой виртуализации тоже влияют: если ваш VDS на медленном сетевом хранилище, особенно избегайте неиндексируемых сортировок/джойнов. Индексы и снижение объёмов данных — ваш лучший друг.

Бинарный лог и репликация

Если вы не используете репликацию или точечное восстановление, можно держать бинарный лог выключенным — он создаёт накладные расходы на запись. Если он нужен, задайте срок хранения через binlog_expire_logs_seconds и контролируйте объёмы. Не забывайте про sync_binlog — баланс между надёжностью и скоростью.

Пошаговый план тюнинга без риска

  1. Снимите базовую метрику: пиковое потребление RAM, наличие свопа, латентность диска, QPS/TPS, ключевые SHOW GLOBAL STATUS и выборки из Performance Schema.
  2. Настройте innodb_buffer_pool_size с запасом для системы и per-connection буферов. Проверьте, что своп не используется в обычном режиме.
  3. Включите slow query log с разумными порогами и прокатайте типичную нагрузку 1–2 дня.
  4. Отсортируйте «сигнатуры» медленных запросов по общей стоимости. Начните с топ-3 и исправьте индексы/планы.
  5. Проверьте redo-параметры: нет ли чрезмерных flush; при необходимости плавно увеличьте ёмкость редо-журнала.
  6. Пересмотрите per-connection буферы и max_connections, чтобы исключить риск OOM при пиках.
  7. Повторяйте цикл: измерить → изменить одну вещь → проверить → зафиксировать.

Чек-лист стартовой конфигурации для VDS с 1 ГБ RAM

  • InnoDB: innodb_buffer_pool_size ~ 600–700 МБ, innodb_buffer_pool_instances=1–2; innodb_flush_log_at_trx_commit=1 (или 2 как компромисс); innodb_flush_method=O_DIRECT (проверить); разумный размер редо.
  • Соединения: max_connections=50–100; sort_buffer_size=1–2 МБ; join_buffer_size=1–2 МБ.
  • Временные таблицы: tmp_table_size=32–64 МБ, max_heap_table_size=32–64 МБ (равные значения).
  • Логи: включить slow query log, задать long_query_time=0.5–1.0, продумать ротацию логов.
  • Performance Schema: оставить включённым, но без избыточных потребителей; периодически снимать срезы по digest/IO waits.
  • Индексы: проверить частые запросы, добавить покрывающие/составные индексы, укрепить селективность, убрать неиспользуемые индексы.
# Пример my.cnf для MySQL 8.0 на VDS с 1 ГБ RAM (базовый старт)
[mysqld]
innodb_buffer_pool_size = 650M
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_redo_log_capacity = 512M

max_connections = 80
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M

slow_query_log = ON
long_query_time = 0.7
log_queries_not_using_indexes = ON
min_examined_row_limit = 1000
log_slow_admin_statements = ON

# Если нужен binlog
# server_id = 1
# binlog_format = ROW
# sync_binlog = 1
# binlog_expire_logs_seconds = 604800

Частые антипаттерны

  • Подняли max_connections до сотен/тысяч — получили лавину памяти.
  • Раздули tmp_table_size и per-connection буферы без анализа — OOM при пиках.
  • Нет составных индексов под реальные фильтры/сортировки — массовые filesort/temporary.
  • Длинные транзакции и «висящие» соединения из пула — накапливается undo/версии.
  • LIKE с ведущим % вместо полнотекстового поиска.
  • UUID как PK без необходимости — рост индексов и фрагментация.
  • Нет ротации slow log/binlog — забивка диска.

MariaDB vs MySQL: мелкие различия, важные на практике

  • Redo-журналы: MySQL 8.0 — innodb_redo_log_capacity, MariaDB — innodb_log_file_size/innodb_log_files_in_group.
  • Функциональные индексы и EXPLAIN ANALYZE: версии и синтаксис отличаются; проверяйте вашу минорную версию.
  • Query Cache: отсутствует в MySQL 8.0, в MariaDB обычно выключают на нагруженных системах.

При переносе конфигов между MySQL и MariaDB не делайте механической замены — сверяйте справку по параметрам именно вашей версии.

Заключение

Базовый тюнинг MySQL/MariaDB на малом VDS — это грамотное распределение памяти (в первую очередь innodb_buffer_pool_size), дисциплина в per-connection буферах, включённый slow query log, разумное использование Performance Schema и уверенная работа с индексами. Такой фундамент уменьшает дисковую активность, повышает кэш-хит и даёт чёткий план улучшений. Дальше — итеративная query optimization: улучшаете топ-3 «дорогих» запросов, переснимаете метрики, повторяете цикл.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...