Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Слияние частей

Что такое слияния частей в ClickHouse?


ClickHouse работает быстро не только при выполнении запросов, но и при вставке данных благодаря своему уровню хранения, который устроен схожим образом с LSM-деревьями:

① Вставки (в таблицы семейства движков MergeTree) создают отсортированные неизменяемые части данных.

② Вся обработка данных переносится в фоновые слияния частей.

Это делает запись данных малозатратной и высокоэффективной.

Чтобы контролировать количество частей в таблице и реализовать описанное в пункте ② выше, ClickHouse непрерывно объединяет (в пределах каждой партиции) меньшие части в более крупные в фоновом режиме, пока их сжатый размер не достигнет примерно ~150 GB.

Следующая диаграмма схематично показывает этот фоновый процесс слияния:

СЛИЯНИЕ ЧАСТЕЙ

уровень слияния части увеличивается на единицу с каждым очередным слиянием. Уровень 0 означает, что часть новая и еще не была объединена. Части, объединенные в более крупные, помечаются как неактивные и затем удаляются через настраиваемый промежуток времени (по умолчанию 8 минут). Со временем это образует дерево слитых частей. Отсюда и название таблицы MergeTree.

Мониторинг слияний

В примере что такое части таблицы мы показали, что ClickHouse отслеживает все части таблицы в системной таблице parts. Мы использовали следующий запрос, чтобы получить уровень слияния и число хранимых строк для каждой активной части таблицы из примера:

SELECT
    name,
    level,
    rows
FROM system.parts
WHERE (database = 'uk') AND (`table` = 'uk_price_paid_simple') AND active
ORDER BY name ASC;

Результат ранее приведённого запроса показывает, что в таблице из примера было четыре активные части, каждая из которых была создана в результате одного слияния изначально вставленных частей:

   ┌─name────────┬─level─┬────rows─┐
1. │ all_0_5_1   │     1 │ 6368414 │
2. │ all_12_17_1 │     1 │ 6442494 │
3. │ all_18_23_1 │     1 │ 5977762 │
4. │ all_6_11_1  │     1 │ 6459763 │
   └─────────────┴───────┴─────────┘

После запуска запроса теперь видно, что четыре части уже слились в одну итоговую часть (при условии, что в таблицу больше не выполняются вставки):

   ┌─name───────┬─level─┬─────rows─┐
1. │ all_0_23_2 │     2 │ 25248433 │
   └────────────┴───────┴──────────┘

В ClickHouse 24.10 во встроенные панели мониторинга была добавлена новая панель мониторинга слияний. Она доступна как в OSS, так и в Cloud через HTTP-обработчик /merges и позволяет визуализировать все слияния частей для таблицы из нашего примера:

СЛИЯНИЕ ЧАСТЕЙ

На записи панели мониторинга выше показан весь процесс — от первоначальных вставок данных до итогового слияния в одну часть:

① Количество активных частей.

② Слияния частей, визуально представленные прямоугольниками (их размер отражает размер части).

Усиление записи.

Параллельные слияния

Один сервер ClickHouse использует несколько фоновых потоков слияния для выполнения параллельных слияний частей:

СЛИЯНИЕ ЧАСТЕЙ

Каждый поток слияния выполняет цикл:

Загрузка частей в память

Определяет, какие части сливать следующими, и загружает их в память.

Слияние частей

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

Запись на диск

Записывает слитую часть на диск, затем возвращается к шагу 1.

Обратите внимание: увеличение числа ядер CPU и объема оперативной памяти позволяет повысить пропускную способность фоновых слияний.

Слияния с оптимизацией по памяти

ClickHouse не обязательно загружает в память все части, подлежащие слиянию, сразу, как показано в предыдущем примере. В зависимости от нескольких факторов и для снижения потребления памяти (ценой скорости слияния) так называемое вертикальное слияние загружает и сливает части фрагментами блоков, а не все сразу.

Механика слияния

Диаграмма ниже показывает, как один фоновый поток слияния в ClickHouse объединяет части (по умолчанию без вертикального слияния):

СЛИЯНИЕ ЧАСТЕЙ

Слияние частей выполняется в несколько этапов:

Декомпрессия и загрузка

сжатые бинарные файлы столбцов из частей, подлежащих слиянию, распаковываются и загружаются в память.

Слияние

Данные сливаются в более крупные файлы столбцов.

Индексация

Для слитых файлов столбцов создаётся новый разреженный первичный индекс.

Сжатие и хранение

Новые файлы столбцов и индекс сжимаются и сохраняются в новом каталоге, который представляет слитую часть данных.

Дополнительные метаданные в частях данных, такие как вторичные индексы пропуска данных, статистика столбцов, контрольные суммы и min-max-индексы, также пересоздаются на основе слитых файлов столбцов. Для простоты мы опустили эти детали.

Механика этапа слияния зависит от конкретного движка MergeTree, поскольку разные движки выполняют слияние по-разному. Например, устаревшие строки могут агрегироваться или заменяться. Как уже упоминалось, такой подход переносит всю обработку данных в фоновые слияния, обеспечивая сверхбыстрые вставки за счёт того, что операции записи остаются лёгкими и эффективными.

Далее мы кратко рассмотрим механику слияния в конкретных движках семейства MergeTree.

Стандартные слияния

На схеме ниже показано, как выполняется слияние частей в стандартной таблице MergeTree:

СЛИЯНИЯ ЧАСТЕЙ

DDL-оператор на схеме выше создаёт таблицу MergeTree с ключом сортировки (town, street), то есть данные на диске сортируются по этим столбцам, и на их основе создаётся разреженный первичный индекс.

① Распакованные предварительно отсортированные столбцы таблицы ② объединяются с сохранением глобального порядка сортировки, заданного ключом сортировки таблицы, ③ создаётся новый разреженный первичный индекс, а ④ объединённые файлы столбцов и индекс сжимаются и сохраняются на диске как новая часть данных.

Слияния в ReplacingMergeTree

Слияния частей в таблице ReplacingMergeTree работают аналогично стандартным слияниям, но сохраняется только самая новая версия каждой строки, а более старые версии отбрасываются:

СЛИЯНИЕ ЧАСТЕЙ

DDL-оператор на диаграмме выше создаёт таблицу ReplacingMergeTree с ключом сортировки (town, street, id), то есть данные на диске сортируются по этим столбцам, а соответствующим образом строится разреженный первичный индекс.

На этапе ② слияние происходит так же, как и в стандартной таблице MergeTree: объединяются распакованные, предварительно отсортированные столбцы с сохранением общего порядка сортировки.

Однако ReplacingMergeTree удаляет дублирующиеся строки с одинаковым ключом сортировки, сохраняя только самую новую строку по временной метке создания части, в которой она находится.


Суммирующие слияния

Числовые данные автоматически суммируются при слиянии частей таблицы SummingMergeTree:

СЛИЯНИЕ ЧАСТЕЙ

DDL-оператор на схеме выше определяет таблицу SummingMergeTree, где town используется как ключ сортировки. Это означает, что данные на диске сортируются по этому столбцу и на его основе создаётся разреженный первичный индекс.

На этапе слияния ② ClickHouse заменяет все строки с одинаковым ключом сортировки одной строкой, суммируя значения числовых столбцов.

Слияния с агрегацией

Пример таблицы SummingMergeTree, приведённый выше, — это специализированный вариант таблицы AggregatingMergeTree, который позволяет выполнять автоматическое инкрементальное преобразование данных, применяя любую из 90+ функций агрегации при слиянии частей:

СЛИЯНИЕ ЧАСТЕЙ

DDL-оператор на диаграмме выше создаёт таблицу AggregatingMergeTree, в которой town используется как ключ сортировки, что гарантирует упорядочивание данных по этому столбцу на диске и создание соответствующего разреженного первичного индекса.

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

Navigation