Партиционирование данных
Партиции делят таблицу на крупные независимые блоки — обычно по месяцам.
Партиционирование (
PARTITION BY) — деление данных таблицы на крупные логические части (например, по месяцам), каждая из которых хранится и обслуживается отдельно.
Партиция — это не то же, что ORDER BY
Легко спутать два понятия. ORDER BY сортирует строки внутри куска и даёт индекс для отсечения гранул. PARTITION BY работает «крупнее»: он раскладывает данные по отдельным партициям, и куски никогда не сливаются между разными партициями. Типичный выбор — партиция по месяцу:
CREATE TABLE events
(
event_date Date,
user_id UInt32,
value Float64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, user_id);Здесь toYYYYMM(event_date) превращает дату в число вида 202401 — все события января 2024 попадут в одну партицию.
Что дают партиции
1. Отсечение целых партиций
Запрос WHERE event_date >= '2024-03-01' позволяет движку сразу отбросить все партиции до марта — он даже не заглядывает в их куски. Это грубое, но очень дешёвое отсечение поверх тонкого отсечения по гранулам.
2. Мгновенное удаление старых данных
Удалить «всё за январь» можно не построчным DELETE, а сбросом целой партиции — это почти мгновенная операция над файлами:
ALTER TABLE events DROP PARTITION 202401;Так удобно соблюдать политику хранения «храним данные год».
Сколько партиций делать
Золотое правило: немного крупных партиций. По месяцам — почти всегда хорошо. По дням на большом сроке — уже много партиций. А вот партиционировать по высококардинальной колонке (например, по user_id) нельзя: получатся десятки тысяч партиций, и сервер захлебнётся в метаданных.
| PARTITION BY | Оценка |
toYYYYMM(date) | отлично — десятки партиций |
toDate(date) (по дням) | осторожно — сотни/тысячи |
user_id | плохо — взрыв числа партиций |
Как работает под капотом
Каждая партиция — это набор кусков с общим значением ключа партиционирования. Слияние идёт только внутри партиции. В метаданных партиции хранятся отдельно, поэтому DROP PARTITION — это удаление файлов, а не сканирование строк.
Частые ошибки
- Слишком мелкие партиции. По дням или по высококардинальному полю — взрыв числа партиций, деградация и предупреждения сервера.
- Путать партицию с индексом. Партиция — грубое деление; тонкую фильтрацию делает ORDER BY/индекс.
- Удалять старое построчным DELETE. Дешевле и быстрее
DROP PARTITIONили TTL.
Итоги
PARTITION BYкрупно делит таблицу (обычно по месяцам).- Партиции отсекаются целиком и удаляются одной операцией.
- Делайте немного крупных партиций; не партиционируйте по высококардинальному полю.
- Партиция дополняет ORDER BY, а не заменяет его.