Раздел 38 · ClickHouse и аналитические базы

Специализированные движки MergeTree

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В уроке про MergeTree мы видели, что части сливаются в фоне. Обычный MergeTree при слиянии просто складывает строки вместе. Его родственники пользуются слиянием, чтобы заодно навести порядок в данных: выбросить старые версии строки, сложить суммы, погасить отменённые записи. Разберём, зачем это нужно и в чём подвох.

Задача: последнее состояние

У каждого курьера «Гонца» есть профиль: зона, транспорт. Курьер переехал в другую зону, профиль поменялся. В PostgreSQL мы бы написали UPDATE. В ClickHouse правка строки дорогая: она переписывает целую часть. Зато дописать новую версию строки дёшево. Пусть таблица хранит все версии, а лишние убирает сама.

Так работает ReplacingMergeTree:

CREATE TABLE couriers (
    id UInt32,
    zone String,
    transport String,
    updated_at DateTime
) ENGINE = ReplacingMergeTree(updated_at)
ORDER BY id;

Строки с одинаковым ключом ORDER BY (здесь id) считаются версиями одного объекта. При слиянии от них остаётся одна, с наибольшим updated_at.

Подвох: слияние когда-нибудь

Слияние идёт в фоне, когда сервер сочтёт нужным. До этого старые и новые версии лежат в разных частях, и обычный SELECT увидит обе. ReplacingMergeTree обещает, что дубли когда-нибудь исчезнут, но не обещает когда. Некоторые дубли не исчезнут никогда: части разных партиций не сливаются.

Поэтому запросы к таким таблицам пишут так, чтобы ответ был верным и до слияния. Есть два способа:

  • слово FINAL после имени таблицы: SELECT * FROM couriers FINAL. ClickHouse схлопнет версии прямо при чтении. Ответ верный, но запрос тяжелее;
  • агрегат argMax: SELECT id, argMax(zone, updated_at) FROM couriers GROUP BY id. Для каждого курьера берётся зона из строки с наибольшим updated_at.

Посмотри сам

Курьер 1 переехал из Центра в ВИЗ. Смотрим таблицу без FINAL, с FINAL и после принудительного слияния.

До слияния обычный запрос вернул три строки: две версии курьера 1. FINAL и argMax дали правильный ответ сразу. После OPTIMIZE старая версия исчезла физически.

урок из курса

Урок из курса «ClickHouse и аналитические базы». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.