Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Движок таблицы TimeSeries

Экспериментальная возможность
Не поддерживается в ClickHouse Cloud

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

metric_name1[tag1=value1, tag2=value2, ...] = {timestamp1: value1, timestamp2: value2, ...}
metric_name2[...] = ...

Синтаксис

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)]]

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

Проще начать с параметров по умолчанию (таблицу 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 CODEC(DoubleDelta, ZSTD(1)), value Float32 CODEC(ZSTD(3)))

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

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

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

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

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

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

Таблица samples

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

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

Имя Обязательно? Тип по умолчанию Возможные типы Описание
id [x] Tuple(UInt64, UUID) любой Идентифицирует комбинацию имени метрики и тегов
timestamp [x] DateTime64(3) DateTime64(X) Момент времени
value [x] Float64 Float32 или Float64 Значение, связанное с timestamp

Столбцы, которые движок создаёт самостоятельно, используют кодеки сжатия временных рядов: timestamp CODEC(DoubleDelta, ZSTD(1)) и value CODEC(ZSTD(3)). Почти монотонные временные метки плохо сжимаются универсальными кодеками и в противном случае могут составлять основную часть размера таблицы samples на диске. См. также Настройка типов столбцов.

Таблица tags

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

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

Имя Обязательный? Тип по умолчанию Возможные типы Описание
id [x] Tuple(UInt64, 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. В таблицах, созданных более старыми версиями ClickHouse, в этом столбце хранились только теги без выделенных столбцов и без имени метрики; чтение поддерживает оба случая
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] 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` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(DoubleDelta, ZSTD(1)),
    `value` Float64 CODEC(ZSTD(3))
)
SAMPLES INNER ENGINE = MergeTree ORDER BY (id, timestamp) SETTINGS index_granularity = 32768
TAGS INNER COLUMNS
(
    `id` Tuple(UInt64, UUID) DEFAULT tuple(sipHash64(metric_name), reinterpretAsUUID(sipHash128(tags))),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `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) SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
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` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(DoubleDelta, ZSTD(1)),
    `value` Float64 CODEC(ZSTD(3))
)
ENGINE = MergeTree
ORDER BY (id, timestamp)
SETTINGS index_granularity = 32768
CREATE TABLE default.`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, UUID) DEFAULT tuple(sipHash64(metric_name), reinterpretAsUUID(sipHash128(tags))),
    `metric_name` LowCardinality(String),
    `tags` Map(LowCardinality(String), String),
    `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)
SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
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
SETTINGS index_granularity = 8192

Создание таблицы 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) CODEC(DoubleDelta, ZSTD(1)), value Float32 CODEC(ZSTD(3)))

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

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

Столбец id

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

CREATE TABLE my_table ENGINE=TimeSeries
TAGS INNER COLUMNS (id UInt64 DEFAULT sipHash64(tags))

Столбец id может иметь любой сопоставимый тип, кроме Nullable. Типы id, объявленные во внутренних таблицах samples и tags, должны совпадать.

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

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

CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_generator = 'sipHash64(tags)'

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

Столбец tags

Столбец tags содержит все теги временного ряда, включая тег __name__ с именем метрики.

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

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

Этот оператор добавит столбцы instance и job во внутреннюю целевую таблицу tags. Значения тегов instance и job будут храниться как в этих столбцах, так и в столбце tags.

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

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

  • таблица 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

Таблица tags хранит столбцы тегов (и Map tags) вне своего ключа сортировки, что AggregatingMergeTree по умолчанию запрещает (см. allow_dimensions_outside_sorting_key). Здесь это безопасно, потому что эти столбцы функционально зависят от id, который является частью ключа сортировки, поэтому все строки, которые объединяются при фоновом слиянии, имеют одинаковые значения. Когда внутренняя таблица tags создаётся или её движок задаётся непосредственно, как показано выше, TimeSeries автоматически устанавливает для неё allow_dimensions_outside_sorting_key = 1; для созданной вручную агрегирующей внешней таблицы tags вы должны установить этот параметр самостоятельно.

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

Таблицу 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(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 карта карта, задающая, какие теги следует вынести в отдельные столбцы таблицы tags. Синтаксис: {'tag1': 'column1', 'tag2' : column2, ...}
use_all_tags_column_to_generate_id Bool false Устаревшая настройка, ничего не делает
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 для фильтрации временных рядов
samples_index_granularity UInt64 32768 Устанавливает index_granularity внутренней таблицы samples. При явной установке переопределяет index_granularity из объявления движка. Игнорируется для внешней таблицы samples и движка, не относящегося к MergeTree
tags_index_granularity UInt64 8192 Устанавливает index_granularity внутренней таблицы tags. При явной установке переопределяет index_granularity из объявления движка. Игнорируется для внешней таблицы tags и движка, не относящегося к MergeTree
recent_samples_ttl_seconds UInt64 345600 Срок хранения дополнительной целевой таблицы recent samples, в которую также записывается каждый вставленный образец. Для внутренней таблицы recent samples всегда задаётся TTL toDateTime(timestamp) + toIntervalSecond(recent_samples_ttl_seconds) на основе этой настройки, переопределяя любой TTL из объявления движка; внешняя таблица recent samples должна хранить данные не менее указанного числа секунд. Запросы, временной диапазон которых укладывается в окно TTL, используют таблицу recent samples предпочтительно перед основной таблицей samples (см. настройку уровня запроса time_series_prefer_recent_samples_table). По умолчанию — 4 дня; действующее значение фиксируется в определении таблицы при выполнении CREATE. Установите значение 0, чтобы отключить таблицу recent samples
recent_samples_partition_by Expression toStartOfInterval(toDateTime(timestamp), toIntervalHour(5)) Ключ партиционирования внутренней таблицы recent samples, например toStartOfHour(timestamp). Требует, чтобы recent_samples_ttl_seconds не был равен нулю
recent_samples_index_granularity UInt64 8192 Устанавливает index_granularity внутренней таблицы recent samples. Требует, чтобы recent_samples_ttl_seconds не был равен нулю

Функции

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

Navigation