Слияние частей
Что такое слияние частей в ClickHouse?
ClickHouse быстрый не только для запросов, но и для вставок, благодаря его слою хранения, который работает аналогично LSM деревьям:
① Вставки (в таблицы от движка MergeTree) создают отсортированные, неизменяемые части данных.
② Все операции обработки данных выполняются в фоновом слиянии частей.
Это делает записи данных легковесными и высокоэффективными.
Чтобы контролировать количество частей в таблице и реализовать ② выше, ClickHouse постоянно сливает (по разделу) меньшие части в более крупные в фоновом режиме, пока они не достигнут сжатого размера примерно ~150 ГБ.
Следующий диаграмма иллюстрирует этот процесс фонового слияния:

Уровень слияния
части увеличивается на единицу с каждым последующим слиянием. Уровень 0
означает, что часть новая и еще не была объединена. Части, которые были объединены в более крупные, помечаются как неактивные и в конечном итоге удаляются после настраиваемого времени (по умолчанию 8 минут). Со временем это создает дерево объединенных частей. Поэтому название дерево слияния.
Мониторинг слияний
В примере что такое части таблицы мы показали, что ClickHouse отслеживает все части таблиц в системной таблице части. Мы использовали следующий запрос для получения уровня слияния и количества храненных строк на каждую активную часть примера таблицы:
[Запуск] (https://sql.clickhouse.com/?query=U0VMRUNUCiAgICBuYW1lLAogICAgbGV2ZWwsCiAgICByb3dzCkZST00gc3lzdGVtLnBhcnRzCldIRVJFIChkYXRhYmFzZSA9ICd1aycpIEFORCAoYHRhYmxlYCA9ICd1a19wcmljZV9wYWlkX3NpbXBsZScpIEFORCBhY3RpdmUKT1JERVIgQlkgbmFtZSBBU0M7&run_query=true&tab=results) запроса сейчас показывает, что четыре части слились в одну финальную часть (если в таблицу не было внесено никаких дополнительных вставок):
В ClickHouse 24.10 была добавлена новая панель мониторинга слияний в встроенные панели мониторинга. Доступная как в OSS, так и в Cloud через HTTP обработчик /merges
, мы можем использовать ее для визуализации всех слияний частей для нашей примерной таблицы:

Записанная панель мониторинга выше фиксирует весь процесс, от начальных вставок данных до окончательного слияния в одну часть:
① Количество активных частей.
② Слияния частей, визуально представлены с помощью коробок (размер отражает размер части).
Параллельные слияния
Один сервер ClickHouse использует несколько фоновых потоков слияния для выполнения параллельных слияний частей:

Каждый поток слияния выполняет цикл:
① Решить, какие части объединить следующими, и загрузить эти части в память.
② Объединить части в памяти в более крупную часть.
③ Записать объединенную часть на диск.
Идем к ①
Обратите внимание, что увеличение количества ядер CPU и объема ОЗУ позволяет увеличить пропускную способность фонового слияния.
Оптимизированные по памяти слияния
ClickHouse не обязательно загружает все части, которые должны быть объединены, в память одновременно, как показано в предыдущем примере. Основываясь на нескольких факторах, и чтобы снизить потребление памяти (жертвуя скоростью слияния), так называемое вертикальное слияние загружает и объединяет части кусками блоков, а не за один раз.
Механика слияния
Диаграмма ниже иллюстрирует, как один фоновый поток слияния в ClickHouse объединяет части (по умолчанию, без вертикального слияния):

Слияние частей выполняется в несколько этапов:
① Декомпрессия и загрузка: Сжатые бинарные файлы столбцов из частей, которые должны быть объединены, декомпрессируются и загружаются в память.
② Слияние: Данные объединяются в более крупные файлы столбцов.
③ Индексация: Новый разреженный первичный индекс генерируется для объединенных файлов столбцов.
④ Сжатие и хранение: Новые файлы столбцов и индекс сжимаются и сохраняются в новой директории, представляющей объединенную часть данных.
Дополнительные метаданные в частях данных, такие как вторичные индексы пропуска данных, статистика столбцов, контрольные суммы и минимальные-максимальные индексы, также воссоздаются на основе объединенных файлов столбцов. Мы опустили эти детали для простоты.
Механика шага ② зависит от конкретного движка MergeTree, используемого, поскольку разные движки обрабатывают слияние по-разному. Например, строки могут агрегироваться или заменяться, если устарели. Как уже упоминалось, этот подход переносит всю обработку данных на фоновое слияние, позволяя сверхбыстрые вставки, сохраняя операции записи легковесными и эффективными.
Далее мы кратко опишем механику слияния конкретных движков в семействе MergeTree.
Стандартные слияния
Диаграмма ниже иллюстрирует, как части в стандартной MergeTree таблице объединяются:

DDL оператор на диаграмме выше создает таблицу MergeTree
с ключом сортировки (город, улица)
, что означает, что данные на диске отсортированы по этим столбцам, и соответственно генерируется разреженный первичный индекс.
Декомпрессированные, предварительно отсортированные ① столбцы таблицы объединяются ②, сохраняя глобальный порядок сортировки таблицы, определяемый ключом сортировки таблицы, ③ генерируется новый разреженный первичный индекс, и ④ объединенные файлы столбцов и индекс сжимаются и сохраняются как новая часть данных на диске.
Заменяющие слияния
Слияние частей в таблице ReplacingMergeTree работает аналогично стандартным слияниям, но сохраняется только самая последняя версия каждой строки, а более старые версии отбрасываются:

DDL оператор на диаграмме выше создает таблицу ReplacingMergeTree
с ключом сортировки (город, улица, id)
, что означает, что данные на диске отсортированы по этим столбцам, с соответствующим разреженным первичным индексом.
Слияние ② работает аналогично стандартной таблице MergeTree
, объединяя декомпрессированные, предварительно отсортированные столбцы, сохраняя глобальный порядок сортировки.
Однако ReplacingMergeTree
удаляет дублирующиеся строки с одинаковым ключом сортировки, оставляя только самую последнюю строку на основе временной метки создания содержащей ее части.
Суммирующие слияния
Числовые данные автоматически суммируются во время слияний частей из таблицы SummingMergeTree:

DDL оператор на диаграмме выше определяет таблицу SummingMergeTree
с городом
в качестве ключа сортировки, что означает, что данные на диске отсортированы по этому столбцу и соответственно генерируется разреженный первичный индекс.
На этапе ② слияния ClickHouse заменяет все строки с тем же ключом сортировки одной строкой, суммируя значения числовых столбцов.
Агрегирующие слияния
Пример таблицы SummingMergeTree
выше является специализированным вариантом таблицы AggregatingMergeTree, позволяющим автоматическое инкрементальное преобразование данных с применением любой из 90+ агрегатных функций во время слияний частей:

DDL оператор на диаграмме выше создает таблицу AggregatingMergeTree
с городом
в качестве ключа сортировки, обеспечивая, что данные упорядочены по этому столбцу на диске и соответствующий разреженный первичный индекс генерируется.
Во время ② слияния ClickHouse заменяет все строки с тем же ключом сортировки одной строкой, хранящей частичные состояния агрегации (например, sum
и count
для avg()
). Эти состояния обеспечивают точные результаты при инкрементальных фоновых слияниях.