Перейти к основному содержимому
Перейти к основному содержимому

Табличный движок TimeSeries

Experimental feature. Learn more.
Not supported in ClickHouse Cloud

Табличный движок для хранения временных рядов, то есть наборов значений, связанных с временными метками и тегами (или метками):

metric_name1[tag1=value1, tag2=value2, ...] = {timestamp1: value1, timestamp2: value2, ...}
metric_name2[...] = ...
Ссылки

Это экспериментальная функция, поведение которой в будущих релизах может измениться без сохранения обратной совместимости. Активируйте использование табличного движка TimeSeries с помощью настройки allow_experimental_time_series_table. Выполните команду set allow_experimental_time_series_table = 1.

Синтаксис

CREATE TABLE name [(columns)] ENGINE=TimeSeries
[SETTINGS var1=value1, ...]
[SAMPLES db.samples_table_name | [SAMPLES INNER COLUMNS (...)] [SAMPLES INNER ENGINE engine(arguments)]]
[TAGS db.tags_table_name | [TAGS INNER COLUMNS (...)] [TAGS INNER ENGINE engine(arguments)]]
[METRICS db.metrics_table_name | [METRICS INNER COLUMNS (...)] [METRICS INNER ENGINE engine(arguments)]]
Примечание

Ключевое слово SAMPLES имеет псевдоним DATA, сохранённый для обеспечения обратной совместимости.

Использование

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

CREATE TABLE my_table ENGINE=TimeSeries

После этого эту таблицу можно использовать со следующими протоколами (порт должен быть указан в конфигурации сервера):

Внешние столбцы

Столбцы таблицы TimeSeries создаются автоматически. Это внешние столбцы: они не хранят данные, а только предоставляют интерфейс для SELECT/INSERT. Фактические данные хранятся в целевых таблицах. Ниже приведён список внешних столбцов:

ИмяТипОписание
metric_nameStringИмя метрики
tagsMap(String, String)Набор тегов (меток) для временного ряда
time_seriesArray(Tuple(DateTime64(3), Float64)) по умолчаниюМассив пар (временная метка, значение) для временного ряда. Типы временной метки и скалярного элемента кортежа можно вывести из объявления INNER COLUMNS для samples (см. Указание внешних столбцов)
metric_familyStringИмя семейства метрик (для метаданных метрик)
typeStringТип метрики (например, "counter", "gauge")
unitStringЕдиница измерения метрики
helpStringОписание метрики

Пример:

INSERT INTO my_table (metric_name, tags, time_series) VALUES
    ('cpu_usage', {'job': 'node_exporter', 'instance': 'host1:9100'},
     [(toDateTime64('2024-01-01 00:00:00', 3), 0.5), (toDateTime64('2024-01-01 00:01:00', 3), 0.7)])

metric_name может быть пустым при вставке; это означает, что имя метрики задаётся в tags, в поле __name__, например:

INSERT INTO my_table (tags, time_series) VALUES
    ({'__name__': 'cpu_usage', 'job': 'test'},
     [(toDateTime64('2024-01-01 00:00:00', 3), 0.5)])

Чтобы вставить метаданные метрик, вставьте значения в столбцы metric_family, type, unit и help:

INSERT INTO my_table (metric_name, tags, time_series, metric_family, type, unit, help) VALUES
    ('http_requests_total', {'method': 'GET'}, [(now64(), 100.0)],
     'http_requests_total', 'counter', 'requests', 'Total HTTP requests')

Указание внешних столбцов

Внешний столбец time_series можно явно указать в операторе CREATE TABLE, чтобы переопределить его тип по умолчанию Array(Tuple(DateTime64(3), Float64)). ClickHouse извлекает тип временной метки и скалярный тип из кортежа и передаёт их внутренней таблице samples:

CREATE TABLE my_table (time_series Array(Tuple(UInt32, Float32))) ENGINE=TimeSeries

Это эквивалентно прямому объявлению типов столбцов временной метки и значения в предложении INNER COLUMNS таблицы samples:

CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp UInt32, value Float32)

Если обе формы используются в одном операторе CREATE TABLE, объявленные типы должны совпадать.

Целевые таблицы

Таблица TimeSeries не имеет собственных данных, всё хранится в её целевых таблицах. Это похоже на работу материализованного представления, с той разницей, что у материализованного представления есть одна целевая таблица, тогда как у таблицы TimeSeries есть три целевые таблицы с именами samples, tags и metrics.

Целевые таблицы могут быть либо указаны явно в запросе CREATE TABLE, либо движок таблицы TimeSeries может автоматически сгенерировать внутренние целевые таблицы.

Строки, вставленные в таблицу TimeSeries, преобразуются, разбиваются на блоки и вставляются в эти три целевые таблицы.

Целевые таблицы следующие:

Таблица samples

Таблица samples содержит временные ряды, связанные с некоторым идентификатором.

Таблица samples должна иметь столбцы:

NameMandatory?Default typePossible typesDescription
id[x]UUIDanyИдентифицирует комбинацию имён метрик и тегов
timestamp[x]DateTime64(3)DateTime64(X)Точка во времени
value[x]Float64Float32 or Float64Значение, связанное с timestamp

Таблица tags

Таблица tags содержит идентификаторы, вычисленные для каждой комбинации имени метрики и тегов.

Таблица tags должна иметь столбцы:

NameMandatory?Default typePossible typesDescription
id[x]UUIDany (must match the type of id in the samples table)id идентифицирует комбинацию имени метрики и тегов. Выражение DEFAULT определяет, как вычисляется такой идентификатор
metric_name[x]LowCardinality(String)String or LowCardinality(String)Имя метрики
<tag_value_column>[ ]StringString or LowCardinality(String) or LowCardinality(Nullable(String))Значение конкретного тега, имя тега и имя соответствующего столбца задаются в настройке tags_to_columns
tags[x]Map(LowCardinality(String), String)Map(String, String) or Map(LowCardinality(String), String) or Map(LowCardinality(String), LowCardinality(String))Карта тегов за исключением тега __name__, содержащего имя метрики, и за исключением тегов с именами, перечисленными в настройке tags_to_columns
all_tags[ ]Map(String, String)Map(String, String) or Map(LowCardinality(String), String) or Map(LowCardinality(String), LowCardinality(String))Эфемерный столбец, каждая строка — это карта всех тегов, за исключением только тега __name__, содержащего имя метрики. Единственная цель этого столбца — использовать его при вычислении id
min_time[ ]Nullable(DateTime64(3))DateTime64(X) or Nullable(DateTime64(X))Минимальная метка времени временных рядов с этим id. Столбец создаётся, если store_min_time_and_max_time имеет значение true
max_time[ ]Nullable(DateTime64(3))DateTime64(X) or Nullable(DateTime64(X))Максимальная метка времени временных рядов с этим id. Столбец создаётся, если store_min_time_and_max_time имеет значение true

Таблица metrics

Таблица metrics содержит сведения о собираемых метриках, их типах и описаниях.

Таблица metrics должна содержать следующие столбцы:

ИмяОбязательный?Тип по умолчаниюВозможные типыОписание
metric_family_name[x]StringString или LowCardinality(String)Имя семейства метрик
type[x]LowCardinality(String)String или LowCardinality(String)Тип семейства метрик, одно из следующих значений: "counter", "gauge", "summary", "stateset", "histogram", "gaugehistogram"
unit[x]LowCardinality(String)String или LowCardinality(String)Единица измерения, используемая в метрике
help[x]StringString или LowCardinality(String)Описание метрики

Создание

Существует несколько способов создать таблицу с движком TimeSeries. Самый простой запрос

CREATE TABLE my_table ENGINE=TimeSeries

фактически создаст следующую таблицу (это можно увидеть, выполнив SHOW CREATE TABLE my_table):

CREATE TABLE my_table
(
    `metric_name` String,
    `tags` Map(String, String),
    `time_series` Array(Tuple(DateTime64(3), Float64)),
    `metric_family` String,
    `type` String,
    `unit` String,
    `help` String
)
ENGINE = TimeSeries
SAMPLES INNER COLUMNS
(
    `id` UUID,
    `timestamp` DateTime64(3),
    `value` Float64
)
SAMPLES INNER ENGINE = MergeTree ORDER BY (id, timestamp)
TAGS INNER COLUMNS
(
    `id` UUID DEFAULT reinterpretAsUUID(sipHash128(metric_name, all_tags)),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `all_tags` Map(String, String) EPHEMERAL,
    `min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
    `max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3)))
)
TAGS INNER ENGINE = AggregatingMergeTree PRIMARY KEY metric_name ORDER BY (metric_name, id)
METRICS INNER COLUMNS
(
    `metric_family_name` String,
    `type` LowCardinality(String),
    `unit` LowCardinality(String),
    `help` String
)
METRICS INNER ENGINE = ReplacingMergeTree ORDER BY metric_family_name

Таким образом, столбцы были сгенерированы автоматически, а также имеются три внутренние целевые таблицы с собственными определениями столбцов, сохранёнными в секциях INNER COLUMNS.

Внутренние целевые таблицы имеют имена вида .inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, .inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, .inner_id.metrics.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, и каждая целевая таблица имеет собственный набор столбцов:

CREATE TABLE default.`.inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` UUID,
    `timestamp` DateTime64(3),
    `value` Float64
)
ENGINE = MergeTree
ORDER BY (id, timestamp)
CREATE TABLE default.`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` UUID DEFAULT reinterpretAsUUID(sipHash128(metric_name, all_tags)),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `all_tags` Map(String, String) EPHEMERAL,
    `min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
    `max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3)))
)
ENGINE = AggregatingMergeTree
PRIMARY KEY metric_name
ORDER BY (metric_name, id)
CREATE TABLE default.`.inner_id.metrics.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `metric_family_name` String,
    `type` LowCardinality(String),
    `unit` LowCardinality(String),
    `help` String
)
ENGINE = ReplacingMergeTree
ORDER BY metric_family_name

Создание таблицы AS по образцу существующей таблицы

Оператор CREATE TABLE new_table AS existing_table копирует из existing_table:

  • SETTINGS
  • INNER COLUMNS для каждого типа
  • INNER ENGINE для каждого типа

Оператор недопустим, если у existing_table есть внешние цели. Внешний список столбцов создаётся заново и не копируется.

Настройка типов столбцов

Вы можете настраивать типы столбцов во внутренних целевых таблицах с помощью конструкции INNER COLUMNS. Например, чтобы хранить временные метки в микросекундах, а значения — в формате Float32:

CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6), value Float32)

Ту же конструкцию можно использовать для указания кодеков и других атрибутов столбца:

CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(3) CODEC(DoubleDelta))

Столбец id

Столбец id содержит идентификаторы; каждый идентификатор вычисляется для сочетания имени метрики и тегов. Тип и выражение DEFAULT, используемое для генерации идентификаторов, можно настроить в секции TAGS INNER COLUMNS:

CREATE TABLE my_table ENGINE=TimeSeries
TAGS INNER COLUMNS (id UInt64 DEFAULT sipHash64(metric_name, all_tags))

Тип столбца id должен быть одним из следующих: UUID, UInt64, UInt128 или FixedString(16). Если выражение DEFAULT не задано, ClickHouse выберет его автоматически в зависимости от типа id. Типы id, объявленные во внутренних таблицах samples и tags, должны совпадать.

Настройка id_generator позволяет выполнить ту же настройку без использования конструкции INNER COLUMNS:

CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_generator = 'sipHash64(metric_name, all_tags)'

Если этот параметр задан, id генерируется на его основе, даже если DEFAULT для столбца содержит другое выражение.

Столбцы tags и all_tags

Есть два столбца, содержащих отображения тегов, — tags и all_tags. В этом примере они по сути эквивалентны, однако могут отличаться, если используется настройка tags_to_columns. Эта настройка позволяет указать, что конкретный тег должен храниться в отдельном столбце вместо хранения в отображении внутри столбца tags:

CREATE TABLE my_table
ENGINE = TimeSeries 
SETTINGS tags_to_columns = {'instance': 'instance', 'job': 'job'}

Этот оператор добавит столбцы instance и job во внутреннюю целевую таблицу tags. В этом случае столбец tags не будет содержать теги instance и job, но столбец all_tags будет содержать их. Столбец all_tags является эфемерным, и его единственное назначение — использоваться в выражении DEFAULT для столбца id.

Движки внутренних целевых таблиц

По умолчанию внутренние целевые таблицы используют следующие движки таблиц:

  • таблица samples использует MergeTree;
  • таблица tags использует AggregatingMergeTree, так как одни и те же данные часто многократно вставляются в эту таблицу, поэтому нам необходим механизм удаления дубликатов, а также потому, что требуется выполнять агрегацию для столбцов min_time и max_time;
  • таблица metrics использует ReplacingMergeTree, так как одни и те же данные часто многократно вставляются в эту таблицу, поэтому нам необходим механизм удаления дубликатов.

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

CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES ENGINE=ReplicatedMergeTree
TAGS ENGINE=ReplicatedAggregatingMergeTree
METRICS ENGINE=ReplicatedReplacingMergeTree

Внешние целевые таблицы

Таблицу TimeSeries можно настроить на использование созданной вручную таблицы:

CREATE TABLE samples_for_my_table
(
    `id` UUID,
    `timestamp` DateTime64(3),
    `value` Float64
)
ENGINE = MergeTree
ORDER BY (id, timestamp);

CREATE TABLE tags_for_my_table ...

CREATE TABLE metrics_for_my_table ...

CREATE TABLE my_table ENGINE=TimeSeries SAMPLES samples_for_my_table TAGS tags_for_my_table METRICS metrics_for_my_table;

Типы столбцов внешних таблиц (id, timestamp, value и столбцов <tag_value_column>, перечисленных в tags_to_columns) должны соответствовать типам, которые таблица TimeSeries иначе сгенерировала бы внутри системы (ограничения типов см. в разделах Samples table, Tags table и Metrics table). О несоответствии типов сообщается во время CREATE.

Выражение генератора id для внешней целевой таблицы тегов вычисляется во время INSERT в следующем порядке: сначала настройка id_generator (если задана), затем DEFAULT, объявленный для столбца id внешней таблицы (если он есть), затем канонический генератор, выведенный из типа id. Таким образом, эта настройка переопределяет любой DEFAULT, объявленный во внешней таблице — подробности см. в разделе The id column.

Изменение параметров

После CREATE можно изменить два параметра:

  • id_generator
  • filter_by_min_time_and_max_time
ALTER TABLE my_table MODIFY SETTING id_generator = 'sipHash64(metric_name, all_tags)';
ALTER TABLE my_table MODIFY SETTING filter_by_min_time_and_max_time = 0;

Обратите внимание: если изменить id_generator, когда в таблице tags уже есть данные, для одной и той же комбинации metric+tag могут создаваться разные ID — старые строки сохраняют прежние ID, а новые используют новый генератор.

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

Настройки

Ниже приведён список настроек, которые можно задать при определении таблицы TimeSeries:

NameTypeDefaultDescription
id_generatorExpressionзависит от типа idВыражение, вычисляющее идентификатор (fingerprint) временного ряда по его тегам. Если оно не задано, используется выражение по умолчанию для столбца id. Если выражение по умолчанию для столбца id также не задано, выражение выбирается автоматически
tags_to_columnsMapОтображение, задающее, какие теги следует вынести в отдельные столбцы в таблице tags. Синтаксис: {'tag1': 'column1', 'tag2' : column2, ...}
use_all_tags_column_to_generate_idBooltrueПри генерации выражения для вычисления идентификатора временного ряда этот флаг включает использование столбца all_tags в этом вычислении
store_min_time_and_max_timeBooltrueЕсли установлено значение true, таблица будет сохранять min_time и max_time для каждого временного ряда
aggregate_min_time_and_max_timeBooltrueПри создании внутренней целевой таблицы tags этот флаг включает использование SimpleAggregateFunction(min, Nullable(DateTime64(3))) вместо просто Nullable(DateTime64(3)) как типа столбца min_time, и аналогично для столбца max_time
filter_by_min_time_and_max_timeBooltrueЕсли установлено значение true, таблица будет использовать столбцы min_time и max_time для фильтрации временных рядов

Функции

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