Движок таблицы для хранения временных рядов, то есть набора значений, связанных с временными метками и тегами (или метками):
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_name | String | Имя метрики |
tags | Map(String, String) | Карта тегов (меток) для временного ряда |
time_series | Array(Tuple(DateTime64(3), Float64)) по умолчанию | Массив пар (временная метка, значение) для временного ряда. Тип временной метки в кортеже и тип его скалярного элемента можно определить по объявлению INNER COLUMNS для samples (см. Указание внешних столбцов) |
metric_family | String | Имя семейства метрик (для метаданных метрик) |
type | String | Тип метрики (например, “counter”, “gauge”) |
unit | String | Единица измерения метрики |
help | String | Описание метрики |
Пример:
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 нет собственных данных — всё хранится в её целевых таблицах.
Это похоже на то, как работает materialized view,
с той разницей, что у materialized view одна целевая таблица,
тогда как у таблицы TimeSeries их три: samples, tags и metrics.
Целевые таблицы можно либо явно указать в запросе CREATE TABLE,
либо движок таблицы TimeSeries может автоматически сгенерировать внутренние целевые таблицы.
Строки, вставленные в таблицу TimeSeries, преобразуются, разбиваются на блоки и вставляются в эти три целевые таблицы.
Целевые таблицы бывают следующими:
Таблица samples содержит временные ряды, связанные с определённым идентификатором.
Таблица samples должна содержать следующие столбцы:
| Имя | Обязательно? | Тип по умолчанию | Возможные типы | Описание |
|---|
id | [x] | UUID | любой | Идентифицирует комбинацию имени метрики и тегов |
timestamp | [x] | DateTime64(3) | DateTime64(X) | Момент времени |
value | [x] | Float64 | Float32 или Float64 | Значение, связанное с timestamp |
Таблица tags содержит идентификаторы, вычисляемые для каждой комбинации имени метрики и тегов.
Таблица tags должна содержать следующие столбцы:
| Имя | Обязательный? | Тип по умолчанию | Возможные типы | Описание |
|---|
id | [x] | UUID | any (must match the type of id in the samples table) | id идентифицирует комбинацию имени метрики и тегов. Выражение DEFAULT задаёт способ вычисления такого идентификатора |
metric_name | [x] | LowCardinality(String) | String or LowCardinality(String) | Имя метрики |
<tag_value_column> | [ ] | String | String 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 должна иметь следующие столбцы:
| Имя | Обязательный? | Тип по умолчанию | Возможные типы | Описание |
|---|
metric_family_name | [x] | String | String или LowCardinality(String) | Имя семейства метрик |
type | [x] | LowCardinality(String) | String или LowCardinality(String) | Тип семейства метрик: один из “counter”, “gauge”, “summary”, “stateset”, “histogram”, “gaugehistogram” |
unit | [x] | LowCardinality(String) | String или LowCardinality(String) | Единица измерения, используемая в метрике |
help | [x] | String | String или 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 содержит идентификаторы; каждый из них вычисляется для комбинации имени метрики и тегов.
Тип и выражение 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_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, таблица Tags и таблица Metrics). О несоответствии типов сообщается во время CREATE.
Выражение генератора id для внешней целевой таблицы tags вычисляется во время INSERT в следующем порядке: сначала настройка id_generator (если она задана), затем DEFAULT, объявленный для столбца id внешней таблицы (если он есть), и затем канонический генератор, определяемый типом id. Таким образом, эта настройка имеет приоритет над любым DEFAULT, объявленным для внешней таблицы — подробности см. в разделе Столбец id.
После 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 могут создаваться разные идентификаторы — старые строки сохранят прежние идентификаторы, а новые будут использовать новый генератор.
Другие настройки нельзя изменить с помощью ALTER ... MODIFY SETTING, потому что они закладываются в схему внутренних таблиц во время CREATE.
Ниже приведён список настроек, которые можно указать при определении таблицы TimeSeries:
| Имя | Тип | По умолчанию | Описание |
|---|
id_generator | Expression | зависит от типа id | Выражение, вычисляющее идентификатор (fingerprint) временного ряда по его тегам. Если не задано, используется выражение по умолчанию для столбца id. Если выражение по умолчанию для столбца id также не задано, выражение выбирается автоматически |
tags_to_columns | Map | Map, задающий, какие теги следует вынести в отдельные столбцы таблицы tags. Синтаксис: {'tag1': 'column1', 'tag2' : column2, ...} | |
use_all_tags_column_to_generate_id | Bool | true | При формировании выражения для вычисления идентификатора временного ряда этот флаг включает использование в вычислении столбца all_tags |
store_min_time_and_max_time | Bool | true | Если установлено значение true, таблица будет хранить min_time и max_time для каждого временного ряда |
aggregate_min_time_and_max_time | Bool | true | При создании внутренней целевой таблицы tags этот флаг включает использование SimpleAggregateFunction(min, Nullable(DateTime64(3))) вместо просто Nullable(DateTime64(3)) в качестве типа столбца min_time; то же самое относится и к столбцу max_time |
filter_by_min_time_and_max_time | Bool | true | Если установлено значение true, таблица будет использовать столбцы min_time и max_time для фильтрации временных рядов |
Ниже приведён список функций, поддерживающих таблицу TimeSeries в качестве аргумента:
Последнее изменение 29 июня 2026 г.