Що таке партиціонування і навіщо воно потрібне
Партиціонування ділить одну логічну таблицю на кілька фізичних частин — секцій, які лежать в окремих файлах, але для запитів виглядають як одна таблиця. Ідея та сама, що й в окремих таблиць за місяцями, тільки сервер сам вирішує, у яку секцію писати і з якої читати, без правок у коді застосунку.
Головний ефект — 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 і читання плану.
Коли партиціонування не допомагає
Є сценарії, де секції лише додають складність без виграшу у швидкості:
- Таблиця невелика — до кількох мільйонів рядків, індексу зазвичай достатньо.
- Запити не фільтрують за стовпцем партиціонування, і 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.
Підсумок: чи варто впроваджувати партиціонування
Перш ніж розбивати таблицю на секції, дайте відповідь на кілька питань:
- Чи росте таблиця настільки, що старі дані хочеться видаляти цілими блоками.
- Чи є у запитів умова на майбутній стовпець партиціонування.
- Чи готові ви включити цей стовпець до первинного ключа.
- Чи потрібні зовнішні ключі на цю таблицю — якщо так, партиціонування не підійде.
- Чи налаштоване автоматичне додавання нових секцій за розкладом.