Skip to main content

SummingMergeTree

Движок наследует функциональность MergeTree. Отличие заключается в том, что для таблиц SummingMergeTree при слиянии кусков данных ClickHouse все строки с одинаковым первичным ключом (точнее, с одинаковым ключом сортировки) заменяет на одну, которая хранит только суммы значений из столбцов с цифровым типом данных. Если ключ сортировки подобран таким образом, что одному значению ключа соответствует много строк, это значительно уменьшает объём хранения и ускоряет последующую выборку данных.

Мы рекомендуем использовать движок в паре с MergeTree. В MergeTree храните полные данные, а SummingMergeTree используйте для хранения агрегированных данных, например, при подготовке отчетов. Такой подход позволит не утратить ценные данные из-за неправильно выбранного первичного ключа.

Создание таблицы​

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = SummingMergeTree([columns])
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

Описание параметров запроса смотрите в описании запроса.

Параметры SummingMergeTree

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

    Если `columns` не задан, то ClickHouse суммирует значения во всех столбцах с числовым типом данных, не входящих в первичный ключ.

Секции запроса

При создании таблицы SummingMergeTree используются те же секции запроса, что и при создании таблицы MergeTree.

Устаревший способ создания таблицы
:::note "Attention"
Не используйте этот способ в новых проектах и по возможности переведите старые проекты на способ описанный выше.
:::
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE [=] SummingMergeTree(date-column [, sampling_expression], (primary, key), index_granularity, [columns])

Все параметры, кроме columns имеют то же значение, что в и MergeTree.

  • columns — кортеж с именами столбцов для суммирования данных. Необязательный параметр. Описание смотрите выше по тексту.

Пример использования​

Рассмотрим следующую таблицу:

CREATE TABLE summtt
(
key UInt32,
value UInt32
)
ENGINE = SummingMergeTree()
ORDER BY key

Добавим в неё данные:

INSERT INTO summtt Values(1,1),(1,2),(2,1)

ClickHouse может не полностью просуммировать все строки (смотрите ниже по тексту), поэтому при запросе мы используем агрегатную функцию sum и секцию GROUP BY.

SELECT key, sum(value) FROM summtt GROUP BY key
┌─key─┬─sum(value)─┐
│ 2 │ 1 │
│ 1 │ 3 │
└─────┴────────────┘

Обработка данных​

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

ClickHouse может слить куски данных таким образом, что не все строки с одинаковым первичным ключом окажутся в одном финальном куске, т.е. суммирование будет не полным. Поэтому, при выборке данных (SELECT) необходимо использовать агрегатную функцию sum() и секцию GROUP BY как описано в примере выше.

Общие правила суммирования​

Суммируются значения в столбцах с числовым типом данных. Набор столбцов определяется параметром columns.

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

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

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

Суммирование в столбцах AggregateFunction​

Для столбцов типа AggregateFunction ClickHouse выполняет агрегацию согласно заданной функции, повторяя поведение движка AggregatingMergeTree.

Вложенные структуры​

Таблица может иметь вложенные структуры данных, которые обрабатываются особым образом.

Если название вложенной таблицы заканчивается на Map и она содержит не менее двух столбцов, удовлетворяющих критериям:

  • первый столбец - числовой (*Int*, Date, DateTime) или строковый (String, FixedString), назовем его условно key,
  • остальные столбцы - арифметические (*Int*, Float32/64), условно (values...),

то вложенная таблица воспринимается как отображение key => (values...) и при слиянии её строк выполняется слияние элементов двух множеств по key со сложением соответствующих (values...).

Примеры:

[(1, 100)] + [(2, 150)] -> [(1, 100), (2, 150)]
[(1, 100)] + [(1, 150)] -> [(1, 250)]
[(1, 100)] + [(1, 150), (2, 150)] -> [(1, 250), (2, 150)]
[(1, 100), (2, 150)] + [(1, -100)] -> [(2, 150)]

При запросе данных используйте функцию sumMap(key, value) для агрегации Map.

Для вложенной структуры данных не нужно указывать её столбцы в кортеже столбцов для суммирования.