> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

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

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

export const PrivatePreviewBadge = () => {
  return <div className="privatePreviewBadge">
            <div className="privatePreviewIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M5.33301 6.66667V4.66667V4.66667C5.33301 3.194 6.52701 2 7.99967 2V2C9.47234 2 10.6663 3.194 10.6663 4.66667V4.66667V6.66667" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path d="M8.00033 9.33337V11.3334" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path fillRule="evenodd" clipRule="evenodd" d="M11.333 14H4.66634C3.92967 14 3.33301 13.4033 3.33301 12.6666V7.99996C3.33301 7.26329 3.92967 6.66663 4.66634 6.66663H11.333C12.0697 6.66663 12.6663 7.26329 12.6663 7.99996V12.6666C12.6663 13.4033 12.0697 14 11.333 14Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            {'Закрытая предварительная версия'}
        </div>;
};

<PrivatePreviewBadge />

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

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

<Info>
  Это возможность в статусе закрытой предварительной версии, которая в будущих релизах может измениться с нарушением обратной совместимости.
  Включите использование движка таблицы TimeSeries
  с помощью настройки `enable_time_series_table`.
  Введите команду `set enable_time_series_table = 1`.
</Info>

<Note>
  Движок таблицы `TimeSeries` доступен в ClickHouse Cloud в статусе закрытой предварительной версии.
  В сервисах, участвующих в закрытой предварительной версии, уже настроена
  настройка `enable_time_series_table`. В других сервисах ClickHouse Cloud
  эта конфигурация отсутствует, и вы не можете самостоятельно включить движок в
  таком сервисе.
</Note>

## Синтаксис

```sql theme={null}
CREATE TABLE name [(columns)] ENGINE=TimeSeries
[SETTINGS var1=value1, ...]
[SAMPLES db.samples_table_name | [SAMPLES INNER COLUMNS (...)] [SAMPLES INNER ENGINE engine(arguments)]]
[RECENT SAMPLES db.recent_samples_table_name | [RECENT SAMPLES INNER COLUMNS (...)] [RECENT SAMPLES INNER ENGINE engine(arguments)]]
[TAGS db.tags_table_name | [TAGS INNER COLUMNS (...)] [TAGS INNER ENGINE engine(arguments)]]
[METRIC FAMILIES db.metric_families_table_name | [METRIC FAMILIES INNER COLUMNS (...)] [METRIC FAMILIES INNER ENGINE engine(arguments)]]
```

<Note>
  У ключевого слова `SAMPLES` есть псевдоним `DATA`, а у ключевого слова `METRIC FAMILIES` — псевдоним `METRICS`; оба сохранены для обратной совместимости.
  Определение таблицы [версии](#schema-versioning) ниже 4 записывается с `METRICS`, чтобы его мог прочитать более старый сервер.
</Note>

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

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
```

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

* [prometheus remote-write](/ru/concepts/features/interfaces/prometheus#remote-write)
* [prometheus remote-read](/ru/concepts/features/interfaces/prometheus#remote-read)

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

Столбцы таблицы TimeSeries создаются автоматически. Это внешние столбцы: они не хранят данные, а лишь предоставляют интерфейс для SELECT/INSERT. Сами данные хранятся в [целевых таблицах](#target-tables). Вот список внешних столбцов:

| Имя | Тип | Описание |
| - | - | - |
| `metric_name` | `String` | Имя метрики |
| `tags` | `Map(String, String)` | Карта тегов (меток) для временного ряда |
| `samples` | `Array(Tuple(DateTime64(3), Float64))` по умолчанию | Массив пар (временная метка, значение) для временного ряда. Тип временной метки в кортеже и тип его скалярного элемента можно определить по объявлению `INNER COLUMNS` для samples (см. [Указание внешних столбцов](#specifying-outer-columns)). В таблицах [версии](#schema-versioning) 2 и ранее столбец называется `time_series` |
| `metric_family` | `String` | Имя семейства метрик (для метаданных метрик) |
| `type` | `String` | Тип метрики (например, "counter", "gauge") |
| `unit` | `String` | Единица измерения метрики |
| `help` | `String` | Описание метрики |

Пример:

```sql theme={null}
INSERT INTO my_table (metric_name, tags, samples) 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__`, например:

```sql theme={null}
INSERT INTO my_table (tags, samples) VALUES
    ({'__name__': 'cpu_usage', 'job': 'test'},
     [(toDateTime64('2024-01-01 00:00:00', 3), 0.5)])
```

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

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

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

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

```sql theme={null}
CREATE TABLE my_table (samples Array(Tuple(UInt32, Float32))) ENGINE=TimeSeries
```

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp UInt32 CODEC(Delta, T64, ZSTD(3)), value Float32 CODEC(ALP, ZSTD(3)))
```

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

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

У таблицы `TimeSeries` нет собственных данных — всё хранится в её целевых таблицах.
Это похоже на то, как работает [materialized view](/ru/reference/statements/create/view#materialized-view),
с той разницей, что у materialized view одна целевая таблица,
тогда как у таблицы `TimeSeries` есть три обязательные целевые таблицы: [samples](#samples-table), [tags](#tags-table) и [metric families](#metric-families-table),
а также необязательная целевая таблица [recent samples](#recent-samples-table), включённая по умолчанию
(см. настройку [recent\_samples\_ttl\_seconds](#settings)).

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

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

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

### Таблица *samples*

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

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

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

Столбцы, которые движок создаёт самостоятельно, используют кодеки сжатия временных рядов:
`timestamp CODEC(Delta, T64, ZSTD(3))` и `value CODEC(ALP, ZSTD(3))`. Почти монотонные временные метки плохо
сжимаются универсальными кодеками и в противном случае могут составлять основную часть размера таблицы samples на диске.
Движок включает `ALP` для своих внутренних таблиц samples и recent samples, не требуя установки `enable_alp_codec`.
См. также [Настройка типов столбцов](#adjusting-column-types).

### Таблица recent samples

Таблица *recent samples* необязательна и включена по умолчанию (см. настройку [recent\_samples\_ttl\_seconds](#settings);
при установке значения `0` таблица отключается). Она содержит копию образцов, возраст которых меньше TTL, заданного этой настройкой,
и должна иметь те же столбцы, что и таблица [samples](#samples-table).
Генерируемый столбец `timestamp` использует `CODEC(Delta, T64, ZSTD(3))`,
а генерируемый столбец `value` — `CODEC(ALP, ZSTD(3))`.

Каждый добавленный образец записывается как в таблицу samples, так и в таблицу recent samples.
Запросы, временной диапазон которых входит в окно TTL, читают данные из таблицы recent samples, а не из основной таблицы samples,
поскольку она значительно меньше (это можно отключить настройкой уровня запроса `time_series_prefer_recent_samples_table`).

TTL внутренней таблицы recent samples всегда определяется настройкой [recent\_samples\_ttl\_seconds](#settings).

### Таблица tags

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

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

| Имя | Обязательный? | Тип по умолчанию | Возможные типы | Описание |
| - | - | - | - | - |
| `id` | \[x] | `Tuple(UInt64, LowCardinality(UUID))` | any (must match the type of `id` in the [samples](#samples-table) 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](#settings) |
| `tags` | \[x] | `Map(LowCardinality(String), String)` | `Map(String, String)` or `Map(LowCardinality(String), String)` or `Map(LowCardinality(String), LowCardinality(String))` | Карта всех тегов, включая тег `__name__`, содержащий имя метрики, а также теги с именами, перечисленными в настройке [tags\_to\_columns](#settings). В таблицах, созданных более старыми версиями ClickHouse, в этом столбце хранились только теги без выделенных столбцов и без имени метрики; чтение поддерживает оба случая |
| `min_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` or `Nullable(DateTime64(X))` | Минимальная временная метка временного ряда с данным `id`. Столбец создаётся, если [store\_min\_time\_and\_max\_time](#settings) имеет значение `true` |
| `max_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` or `Nullable(DateTime64(X))` | Максимальная временная метка временного ряда с данным `id`. Столбец создаётся, если [store\_min\_time\_and\_max\_time](#settings) имеет значение `true` |

Новые внутренние таблицы tags [версии](#schema-versioning) 5 и выше с движком семейства `MergeTree` имеют инвертированный текстовый индекс по `tags`:
`INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs')`. Он ускоряет точные совпадения меток, например
`{job="api"}` в PromQL, за счёт совместного поиска по ключу и значению. Сравнения с пустой строкой также
соответствуют отсутствующим меткам и не используют этот индекс.

Явные индексы, объявленные в `TAGS INNER COLUMNS`, заменяют индекс по умолчанию. Существующие таблицы и внешние
таблицы tags сохраняют свои индексы; чтобы включить индекс, добавьте и материализуйте его в их целевой таблице tags.

### Таблица metric families

Таблица *metric families* содержит информацию о собираемых семействах метрик, их типах и описаниях.
Семейство метрик — это группа метрик с одинаковым именем (тег `__name__`) и одинаковым типом; например, histogram — это семейство метрик, состоящее из нескольких метрик.

Таблица *metric families* должна иметь следующие столбцы:

| Имя | Обязательный? | Тип по умолчанию | Возможные типы | Описание |
| - | - | - | - | - |
| `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`.
Самый простой оператор

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
```

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

```sql theme={null}
CREATE TABLE my_table
(
    `metric_name` String,
    `tags` Map(String, String),
    `samples` Array(Tuple(DateTime64(3), Float64)),
    `metric_family` String,
    `type` String,
    `unit` String,
    `help` String
)
ENGINE = TimeSeries
SETTINGS version = 5, recent_samples_ttl_seconds = 345600
SAMPLES INNER COLUMNS
(
    `id` Tuple(UInt64, LowCardinality(UUID)),
    `timestamp` DateTime64(3) CODEC(Delta, T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
SAMPLES INNER ENGINE = MergeTree ORDER BY (id, timestamp) SETTINGS index_granularity = 32768
RECENT SAMPLES INNER COLUMNS
(
    `id` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(Delta, T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
RECENT SAMPLES INNER ENGINE = MergeTree PARTITION BY toStartOfInterval(toDateTime(timestamp), toIntervalHour(5)) ORDER BY (id, timestamp) TTL toDateTime(timestamp) + toIntervalSecond(345600) SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
TAGS INNER COLUMNS
(
    `id` Tuple(UInt64, LowCardinality(UUID)) DEFAULT tuple(sipHash64(metric_name), toLowCardinality(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))),
    INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs') GRANULARITY 100000000
)
TAGS INNER ENGINE = AggregatingMergeTree PRIMARY KEY metric_name ORDER BY (metric_name, id) SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
METRIC FAMILIES INNER COLUMNS
(
    `metric_family_name` String,
    `type` LowCardinality(String),
    `unit` LowCardinality(String),
    `help` String
)
METRIC FAMILIES INNER ENGINE = ReplacingMergeTree ORDER BY metric_family_name
```

Столбцы были созданы автоматически, а также имеются четыре внутренних целевых таблицы с собственными определениями столбцов,
хранящимися в конструкциях `INNER COLUMNS`. Настройка `recent_samples_ttl_seconds` была записана в конструкцию `SETTINGS`
со значением по умолчанию: эта настройка определяет TTL таблицы recent samples, поэтому её фактическое значение фиксируется при создании.
Также последняя версия схемы была зафиксирована в настройке `version` (см. [Версионирование схемы](#schema-versioning)).

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

```sql theme={null}
CREATE TABLE default.`.inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, LowCardinality(UUID)),
    `timestamp` DateTime64(3) CODEC(Delta(8), T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
ENGINE = MergeTree
ORDER BY (id, timestamp)
SETTINGS index_granularity = 32768
```

```sql theme={null}
CREATE TABLE default.`.inner_id.recentsamples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, UUID),
    `timestamp` DateTime64(3) CODEC(Delta(8), T64, ZSTD(3)),
    `value` Float64 CODEC(ALP, ZSTD(3))
)
ENGINE = MergeTree
PARTITION BY toStartOfInterval(toDateTime(timestamp), toIntervalHour(5))
ORDER BY (id, timestamp)
TTL toDateTime(timestamp) + toIntervalSecond(345600)
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
```

```sql theme={null}
CREATE TABLE default.`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
    `id` Tuple(UInt64, LowCardinality(UUID)) DEFAULT tuple(sipHash64(metric_name), toLowCardinality(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))),
    INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs') GRANULARITY 100000000
)
ENGINE = AggregatingMergeTree
PRIMARY KEY metric_name
ORDER BY (metric_name, id)
SETTINGS allow_dimensions_outside_sorting_key = 1, index_granularity = 8192
```

```sql theme={null}
CREATE TABLE default.`.inner_id.metricfamilies.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` создаёт таблицу `TimeSeries` с той же конфигурацией, что и у `existing_table`,
которая должна быть таблицей `TimeSeries`. Внешние целевые таблицы (external targets) `existing_table` не копируются: оператор должен
объявить их самостоятельно.

Из `existing_table` копируются:

* предложение `SETTINGS`, кроме `version`: новая таблица всегда получает последнюю версию. Настройки, указанные в самом
  операторе, объединяются со скопированными по имени, поэтому указанная настройка имеет приоритет над скопированной, а `name = DEFAULT`
  сбрасывает скопированную настройку к значению по умолчанию;
* предложения `INNER COLUMNS` и `INNER ENGINE` каждой внутренней таблицы. Изменённые вручную столбцы (например, дополнительные столбцы, столбцы
  с кодеком или выражением DEFAULT) и изменённые вручную части движка (например, движок с аргументами, пользовательский ключ сортировки
  или настройка движка) сохраняются, остальные столбцы и части движка приводятся в соответствие настройкам новой таблицы — так, чтобы,
  например, указанные в операторе `tags_to_columns`, `aggregate_min_time_and_max_time` или `tags_index_granularity` вступили в силу.

Типы столбцов `id`, временной метки и значения, а также тип репликации внутренних движков (`MergeTree`,
`ReplicatedMergeTree` или `SharedMergeTree`) также берутся из `existing_table`, если оператор не задаёт их явно.
Список внешних столбцов генерируется заново, а не копируется.

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

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

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6) CODEC(Delta, T64, ZSTD(3)), value Float32 CODEC(ALP, ZSTD(3)))
```

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6), value Float32)
```

## Столбец `id`

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

```sql theme={null}
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)`, те же типы, обёрнутые в `LowCardinality`, или кортежем из двух таких типов. Для такого кортежа автоматически выбранное выражение вычисляет хеш имени метрики в первом компоненте и хеш всех тегов во втором компоненте.

Тип идентификатора `LowCardinality`, например `Tuple(UInt64, LowCardinality(UUID))`, хранит идентификаторы в словарной кодировке: таблица samples сохраняет небольшие словари для каждого блока с индексами словаря вместо повторения полного идентификатора в каждой строке, что уменьшает объём данных, считываемых запросами.

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_generator = 'sipHash64(tags)'
```

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

Тип столбца `id` также можно указать в параметре `id_type` вместо предложения `INNER COLUMNS`:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_type = 'UInt64', id_generator = 'sipHash64(tags)'
```

Если параметр `id_generator` задан, параметр `id_type` записывается автоматически при выполнении `CREATE`,
поэтому в определении сохраняется тип, для которого было написано выражение.

## Столбец `tags`

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

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

```sql theme={null}
CREATE TABLE my_table
ENGINE = TimeSeries
SETTINGS tags_to_columns = {'instance': 'instance', 'job': 'job'}
```

Этот оператор добавит столбцы `instance` и `job` во внутреннюю целевую [таблицу `tags`](#tags-table).
Значения тегов `instance` и `job` будут храниться как в этих столбцах, так и в столбце `tags`.

<Note>
  В таблицах, созданных более ранними версиями ClickHouse, столбец `tags` содержит только теги без выделенных
  столбцов и без имени метрики, а столбец `all_tags` является эфемерным столбцом, который при вставке заполнялся
  всеми тегами, кроме имени метрики.
</Note>

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

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

* таблица [samples](#samples-table) использует [MergeTree](/ru/reference/engines/table-engines/mergetree-family/mergetree);
* таблица [recent samples](#recent-samples-table) использует [MergeTree](/ru/reference/engines/table-engines/mergetree-family/mergetree), разбитый на 5-часовые бакеты (см. настройку [recent\_samples\_partition\_by](#settings)), с `TTL`, определяемым
  настройкой [recent\_samples\_ttl\_seconds](#settings), и с включённым `ttl_only_drop_parts`, поэтому устаревшие части удаляются целиком;
* таблица [tags](#tags-table) использует [AggregatingMergeTree](/ru/reference/engines/table-engines/mergetree-family/aggregatingmergetree), поскольку одни и те же данные часто вставляются в эту таблицу несколько раз, поэтому необходим способ
  удалять дубликаты, а также потому, что для столбцов `min_time` и `max_time` требуется выполнять агрегацию;
* таблица [metric families](#metric-families-table) использует [ReplacingMergeTree](/ru/reference/engines/table-engines/mergetree-family/replacingmergetree), поскольку одни и те же данные часто вставляются в эту таблицу несколько раз, поэтому необходим способ
  удалять дубликаты.

Семейство движков создаваемых внутренних таблиц определяется настройкой уровня запроса `default_table_engine`:
при `default_table_engine = ReplicatedMergeTree` или `SharedMergeTree` внутренние таблицы используют соответствующие
движки `Replicated` или `Shared`. При `default_table_engine = None` (или любом другом значении) движки внутренних таблиц
должны быть указаны явно.

Все внутренние таблицы должны иметь одинаковый тип репликации: если одна из них реплицируемая (или общая), остальные внутренние
таблицы также должны быть реплицируемыми (или общими), иначе их содержимое будет различаться между репликами. Например,
объявление `SAMPLES INNER ENGINE = ReplicatedMergeTree(...)` требует, чтобы остальные внутренние движки также были реплицируемыми —
либо объявленными явно, либо созданными с `default_table_engine = ReplicatedMergeTree`.

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

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES ENGINE=ReplicatedMergeTree
RECENT SAMPLES ENGINE=ReplicatedMergeTree
TAGS ENGINE=ReplicatedAggregatingMergeTree
METRIC FAMILIES ENGINE=ReplicatedReplacingMergeTree
```

Таблица [tags](#tags-table) хранит столбцы тегов (и Map `tags`) вне своего ключа сортировки,
что `AggregatingMergeTree` по умолчанию запрещает (см. [`allow_dimensions_outside_sorting_key`](/ru/reference/engines/table-engines/mergetree-family/aggregatingmergetree)).
Здесь это безопасно, потому что эти столбцы функционально зависят от `id`, который является частью ключа сортировки, поэтому все
строки, которые объединяются при фоновом слиянии, имеют одинаковые значения. Когда внутренняя таблица tags создаётся или её
движок задаётся непосредственно, как показано выше, `TimeSeries` автоматически устанавливает для неё `allow_dimensions_outside_sorting_key = 1`;
для созданной вручную агрегирующей [внешней](#external-target-tables) таблицы tags вы должны установить этот параметр самостоятельно.

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

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

```sql theme={null}
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 metric_families_for_my_table ...

CREATE TABLE my_table ENGINE=TimeSeries SAMPLES samples_for_my_table TAGS tags_for_my_table METRIC FAMILIES metric_families_for_my_table;
```

Внешнюю таблицу также можно использовать в качестве целевой таблицы для [recent samples](#recent-samples-table) (предложение `RECENT SAMPLES my_recent_samples_table`).
Такая таблица должна иметь те же столбцы, что и внешняя таблица samples, и должна хранить данные не менее
[recent\_samples\_ttl\_seconds](#settings) секунд, за что отвечает пользователь.

Типы столбцов внешних таблиц (`id`, `timestamp`, `value` и `<tag_value_column>`, перечисленные в [`tags_to_columns`](#settings)) должны совпадать с теми, которые таблица `TimeSeries` в противном случае сгенерировала бы внутри системы (ограничения на типы см. в разделах [таблица Samples](#samples-table), [таблица Tags](#tags-table) и [таблица Metric families](#metric-families-table)). О несоответствии типов сообщается во время `CREATE`.

Тип столбца `id` внешней таблицы tags и выражение, генерирующее идентификаторы, записываются в настройки [`id_type`](#settings) и [`id_generator`](#settings) во время `CREATE` (начиная с [версии](#schema-versioning) 2), поэтому определение таблицы `TimeSeries` сохраняет их: например, `CREATE TABLE ... AS my_table` считывает тип `id` из определения `my_table`, не обращаясь к её внешним целевым таблицам. Если настройка `id_generator` не задана, ей присваивается значение `DEFAULT`, объявленное для столбца `id` внешней таблицы (если оно есть), в противном случае — канонический генератор, определяемый типом `id`. Записанное выражение используется для генерации `id`, даже если `DEFAULT` внешней таблицы впоследствии изменится — подробности см. в разделе [Столбец `id`](#id-column).

## Изменение настроек

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

* `id_generator`
* `filter_by_min_time_and_max_time`

```sql theme={null}
ALTER TABLE my_table MODIFY SETTING id_generator = 'sipHash64(tags)';
ALTER TABLE my_table MODIFY SETTING filter_by_min_time_and_max_time = 0;
ALTER TABLE my_table RESET SETTING filter_by_min_time_and_max_time;
```

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

Другие настройки нельзя изменить с помощью `ALTER ... MODIFY SETTING`: большинство из них закладываются в схему внутренних таблиц во время `CREATE`,
а настройка `version` фиксируется автоматически во время `CREATE` и идентифицирует саму схему (см. [Версионирование схемы](#schema-versioning)).

## Настройки

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

| Имя | Тип | По умолчанию | Описание |
| - | - | - | - |
| `id_type` | Тип данных | зависит от столбца `id` | Тип столбца `id` целевых таблиц. Обычно тип объявляется в предложениях `INNER COLUMNS` внутренних таблиц или во [внешней](#external-target-tables) таблице tags; настройка записывается автоматически при выполнении `CREATE`, если иначе тип не сохраняется в определении: если целевая таблица tags является внешней либо если задана настройка `id_generator`. Настройку также можно указать явно вместо `TAGS INNER COLUMNS (id <type>)`. Требует, чтобы `version` был не менее 2 |
| `id_generator` | Expression | зависит от типа `id` | Выражение, вычисляющее идентификатор (fingerprint) временного ряда по его тегам. Если не задано, используется выражение по умолчанию для столбца `id`. Если выражение по умолчанию для столбца `id` также не задано, выражение выбирается автоматически. Для внешней таблицы tags настройка записывается автоматически при выполнении `CREATE`, если `version` не меньше 2 (см. [Внешние целевые таблицы](#external-target-tables)) |
| `tags_to_columns` | карта | {} | карта, задающая, какие теги следует вынести в отдельные столбцы таблицы [tags](#tags-table). Синтаксис: `{'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](#samples-table). При явной установке переопределяет `index_granularity` из объявления движка. Игнорируется для внешней таблицы samples и движка, не относящегося к 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)`. При явной установке переопределяет ключ партиционирования из объявления движка; если не задано ни то ни другое, используется одна партиция на каждые 5 часов. Игнорируется для внешней таблицы recent samples. Требует, чтобы `recent_samples_ttl_seconds` не был равен нулю |
| `recent_samples_index_granularity` | UInt64 | 8192 | Устанавливает `index_granularity` внутренней таблицы `recent samples`. При явной установке переопределяет `index_granularity` из объявления движка. Игнорируется для внешней таблицы recent samples и движка, не относящегося к MergeTree. Требует, чтобы `recent_samples_ttl_seconds` не был равен нулю |
| `tags_index_granularity` | UInt64 | 8192 | Устанавливает `index_granularity` внутренней таблицы [tags](#tags-table). При явной установке переопределяет `index_granularity` из объявления движка. Игнорируется для внешней таблицы tags и движка, не относящегося к MergeTree |
| `version` | UInt64 | 5 | Версия таблицы: определяет набор целевых таблиц и их структуру. Версия фиксируется автоматически при создании таблицы и не может быть изменена впоследствии; обычно её следует опускать в запросе `CREATE TABLE` (см. [Версионирование схемы](#schema-versioning)) |

## Версионирование схемы

Движок таблицы `TimeSeries` и слой выполнения PromQL активно развиваются:
набор целевых таблиц и их структура могут меняться от версии к версии ClickHouse.
Чтобы такие изменения можно было отследить, каждая таблица `TimeSeries` хранит свою версию в настройке [version](#settings).
Версия автоматически фиксируется в запросе `CREATE` при создании таблицы — её значением становится последняя версия, известная серверу (сейчас 5), —
сохраняется в метаданных таблицы и не может быть изменена с помощью `ALTER`. Таблицы, созданные до появления этой настройки, считаются таблицами версии 0.
Обычно эту настройку достаточно просто не указывать в запросе `CREATE TABLE` — тогда таблица получит последнюю версию.
Явно заданное значение `version` принимается, если сервер поддерживает эту версию; в этом случае таблица определяется так, как это делает соответствующая версия (см. [История версий](#version-history)).
`CREATE TABLE ... AS other_table` не копирует версию другой таблицы, см. [Создание таблицы AS на основе существующей таблицы](#create-as).

Сервер поддерживает диапазон версий, причём минимальная версия может отличаться для чтения через `SELECT`, для записи через `INSERT`
или по протоколу Prometheus remote-write, а также для вычисления PromQL (табличные функции [prometheusQuery](/ru/reference/functions/table-functions/prometheusQuery),
[prometheusQueryRange](/ru/reference/functions/table-functions/prometheusQueryRange),
и [timeSeriesSelector](/ru/reference/functions/table-functions/timeSeriesSelector),
диалект `promql` и HTTP query API Prometheus):

* Если версия таблицы `TimeSeries` слишком старая для PromQL, запросы PromQL к ней отклоняются. В тексте исключения предлагается пересоздать таблицу:
  создайте новую таблицу `TimeSeries`, скопируйте данные запросом `INSERT ... SELECT` и замените старую таблицу новой.
* Если версия слишком старая для записи, запросы `INSERT` и протокол Prometheus remote-write отклоняются, при этом запросы `SELECT` продолжают работать.
* Если версия слишком старая для сервера в принципе, отклоняется любой запрос к таблице (кроме `SHOW CREATE TABLE`, `DETACH` и `DROP`).

### История версий

| Версия | Изменения |
| - | - |
| 0 | Таблицы, созданные до появления настройки `version`, включая «prealpha»-таблицы (в которых столбцы целевых таблиц объявлялись как [внешние столбцы](#outer-columns)) и таблицы без таблицы [recent samples](#recent-samples-table) |
| 1 | Появилась настройка `version` |
| 2 | Появилась настройка [`id_type`](#settings): таблица с внешней таблицей tags записывает тип столбца `id` в `id_type`, а выражение, генерирующее идентификаторы, — в [`id_generator`](#settings), поэтому её определение не зависит от внешней таблицы. `id_type` также записывается, когда задан `id_generator` (см. [Столбец `id`](#id-column)) |
| 3 | Внешний столбец `time_series` переименован в `samples` (см. [внешние столбцы](#outer-columns)). В таблицах более ранних версий сохраняется прежнее имя столбца, а табличные функции [prometheusQuery](/ru/reference/functions/table-functions/prometheusQuery) и [prometheusQueryRange](/ru/reference/functions/table-functions/prometheusQueryRange) возвращают столбец под тем именем, которое использует таблица. Сохранённые данные не изменились |
| 4 | Целевая таблица `metrics` переименована в `metric families`: внутренняя таблица называется `.inner_id.metricfamilies.<uuid>` вместо `.inner_id.metrics.<uuid>`, а определение записывается с ключевым словом `METRIC FAMILIES` вместо `METRICS`. Сохранённые данные не изменились |
| 5 | Новые внутренние таблицы tags с движком семейства `MergeTree` по умолчанию получают текстовый индекс `keyValuePairs` по map `tags` (см. [таблица tags](#tags-table)) |

# Функции

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

* [timeSeriesSamples](/ru/reference/functions/table-functions/timeSeriesSamples)
* [timeSeriesTags](/ru/reference/functions/table-functions/timeSeriesTags)
* [timeSeriesMetricFamilies](/ru/reference/functions/table-functions/timeSeriesMetricFamilies)
