Движки таблиц и семейство MergeTree
Движок таблицы решает, как данные лежат на диске и что с ними можно делать.
Движок таблицы (table engine) в ClickHouse — указанный при
CREATE TABLEкомпонент, который определяет способ хранения, индексирования и обработки данных.
Зачем вообще движки
В обычной базе вы пишете CREATE TABLE и не думаете о движке. В ClickHouse движок — обязательный и осознанный выбор: именно он задаёт, как строки физически хранятся, есть ли первичный ключ, как идёт вставка, как происходит слияние данных. Семейство MergeTree — основной выбор для аналитики; почти все «настоящие» таблицы используют его или его варианты.
Простейшая таблица на MergeTree
CREATE TABLE events
(
event_date Date,
user_id UInt32,
event_type String,
value Float64
)
ENGINE = MergeTree
ORDER BY (event_date, user_id);Обязательны две вещи: ENGINE = MergeTree и ORDER BY. Про ORDER BY — отдельный урок, это ключ к скорости.
Данные хранятся кусками (parts)
Каждая вставка в MergeTree создаёт на диске отдельный кусок (part) — самостоятельную мини-таблицу с отсортированными по ORDER BY данными и индексом. Схематично:
INSERT #1 --> part_1 [отсортированные строки + индекс] INSERT #2 --> part_2 [отсортированные строки + индекс] INSERT #3 --> part_3 [отсортированные строки + индекс]
«Merge» в названии — про то, что фоновый процесс сливает мелкие куски в крупные:
part_1 + part_2 + part_3 --(фоновое слияние)--> part_big
Почему слияние важно
Много мелких кусков = медленные запросы (нужно заглянуть в каждый) и нагрузка на файловую систему. Слияние укрупняет куски, снова сортирует данные по ORDER BY и применяет дедупликацию/агрегацию (в специальных версиях движка). Это и есть «дерево слияний» — LSM-подобная идея: пишем быстро мелкими кусками, потом фоном наводим порядок.
Как работает под капотом
Внутри куска данные каждой колонки лежат отдельным сжатым файлом, отсортированы по ORDER BY, и к ним есть разрежённый индекс (засечки через каждые ~8192 строки). При запросе ClickHouse по индексу отбрасывает целые гранулы, которые точно не нужны, и читает только подходящие — это называется prune (отсечение).
Частые ошибки
- Вставлять по одной строке. Каждый INSERT — отдельный part; тысячи мелких вставок = тысячи кусков, слияние не успевает, ошибка «too many parts». Вставляйте батчами.
- Брать неподходящий движок. Для аналитической таблицы это почти всегда MergeTree-семейство, а не Log или Memory.
Итоги
- Движок задаёт способ хранения и обработки; MergeTree — основной для аналитики.
- Каждая вставка создаёт отдельный кусок (part), отсортированный по ORDER BY.
- Фоновое слияние укрупняет куски и наводит порядок.
- Мелкие частые вставки порождают слишком много кусков — это плохо.