# Партиционирование таблиц MySQL: когда оно помогает

> Партиционирование MySQL по RANGE и HASH: когда ускоряет запросы, а когда только усложняет схему. Примеры создания секций и их удаления.

## Что такое партиционирование и зачем оно нужно

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

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

## Виды партиционирования: RANGE, LIST, HASH

В MySQL и MariaDB доступно несколько типов:

| Тип | Принцип деления | Типичный сценарий |
| --- | --- | --- |
| RANGE | По диапазону значений столбца | Логи и заказы по дате |
| LIST | По фиксированному списку значений | Данные по регионам или статусам |
| HASH | По хеш-функции от столбца | Равномерное распределение без явного ключа |
| KEY | Как HASH, но на встроенной функции MySQL | Быстрое разделение без своей формулы |

RANGE по дате — самый частый случай на практике: старые партиции легко удалить целиком одной командой вместо медленного DELETE по миллионам строк.

## Пример: партиционирование таблицы логов по месяцам

Партиционирование задаётся при создании таблицы через PARTITION BY:

```
CREATE TABLE access_log (
  id BIGINT AUTO_INCREMENT,
  created_at DATE NOT NULL,
  ip VARCHAR(45),
  PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (TO_DAYS(created_at)) (
  PARTITION p2026_01 VALUES LESS THAN (TO_DAYS('2026-02-01')),
  PARTITION p2026_02 VALUES LESS THAN (TO_DAYS('2026-03-01')),
  PARTITION pmax VALUES LESS THAN MAXVALUE
);
```

Обратите внимание: столбец партиционирования обязан входить в первичный ключ. Это ограничение MySQL, и его нельзя обойти — приходится проектировать ключ заранее, до появления реальных данных.

## Как удалить старые данные без DELETE

Вместо медленного `DELETE FROM access_log WHERE created_at < '2026-01-01'`, которое пишет в бинлог по строке, партицию можно отбросить целиком:

```
ALTER TABLE access_log DROP PARTITION p2026_01;
```

Операция почти мгновенная, потому что физически удаляется файл партиции, а не строки из него. Для таблиц с логами и метриками это основная причина внедрять партиционирование. Подробнее о том, как читать план запроса и убедиться, что pruning действительно работает, — в статье про [EXPLAIN и чтение плана](https://www.zevshost.net/ru/kb/mysql-explain-plan-zaprosa/).

## Когда партиционирование не помогает

Есть сценарии, где секции только добавляют сложность без выигрыша в скорости:

- Таблица небольшая — до нескольких миллионов строк, индекса обычно достаточно.
- Запросы не фильтруют по столбцу партиционирования, и pruning не срабатывает.
- Много запросов с JOIN по внешнему ключу, не совпадающему со столбцом партиций.
- Внешние ключи на партиционированную таблицу — MySQL их не поддерживает вовсе.

## Обслуживание партиций: добавление и реорганизация

Новые партиции для будущих месяцев стоит создавать заранее по расписанию через cron, иначе вставка в pmax накапливает все новые строки в одной большой секции:

```
ALTER TABLE access_log REORGANIZE PARTITION pmax INTO (
  PARTITION p2026_03 VALUES LESS THAN (TO_DAYS('2026-04-01')),
  PARTITION pmax VALUES LESS THAN MAXVALUE
);
```

После реорганизации проверьте распределение строк по секциям через `information_schema.partitions`, чтобы убедиться, что данные не скопились в одной партиции. Если партиции стали крупнее, чем рассчитывал буферный пул, пересмотрите его размер в статье про [настройку my.cnf](https://www.zevshost.net/ru/kb/mysql-my-cnf-optimizatsiya/).

## Итог: стоит ли внедрять партиционирование

Перед тем как разбивать таблицу на секции, ответьте на несколько вопросов:

- Растёт ли таблица настолько, что старые данные хочется удалять целыми блоками.
- Есть ли у запросов условие на будущий столбец партиционирования.
- Готовы ли вы включить этот столбец в первичный ключ.
- Нужны ли внешние ключи на эту таблицу — если да, партиционирование не подойдёт.
- Настроено ли автоматическое добавление новых партиций по расписанию.

---

Источник: https://www.zevshost.net/ru/kb/mysql-particionirovanie/
