# Партиціонування таблиць 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/uk/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/uk/kb/mysql-my-cnf-optimizatsiya/).

## Підсумок: чи варто впроваджувати партиціонування

Перш ніж розбивати таблицю на секції, дайте відповідь на кілька питань:

- Чи росте таблиця настільки, що старі дані хочеться видаляти цілими блоками.
- Чи є у запитів умова на майбутній стовпець партиціонування.
- Чи готові ви включити цей стовпець до первинного ключа.
- Чи потрібні зовнішні ключі на цю таблицю — якщо так, партиціонування не підійде.
- Чи налаштоване автоматичне додавання нових секцій за розкладом.

---

Джерело: https://www.zevshost.net/uk/kb/mysql-particionirovanie/
