До основного вмісту

Партиціонування таблиць MySQL: коли це допомагає

MySQL / MariaDB · 29.09.2026

Що таке партиціонування і навіщо воно потрібне

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

Головний ефект — 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.

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

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

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