> ## 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.

> Um motor de tabela que armazena séries temporais, ou seja, um conjunto de valores associado a timestamps e tags (ou labels).

# motor de tabela 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>
            {'Em prévia privada'}
        </div>;
};

<PrivatePreviewBadge />

Um motor de tabela que armazena séries temporais, ou seja, um conjunto de valores associados a timestamps e tags (ou labels):

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

<Info>
  Este é um recurso em visualização privada que pode mudar de formas incompatíveis com versões anteriores em lançamentos futuros.
  Habilite o uso do motor de tabela TimeSeries
  com a configuração `enable_time_series_table`.
  Execute o comando `set enable_time_series_table = 1`.
</Info>

<Note>
  O motor de tabela `TimeSeries` está disponível no ClickHouse Cloud como um recurso em visualização privada.
  Os serviços que participam da visualização privada já possuem a configuração
  `enable_time_series_table` definida. Outros serviços do ClickHouse Cloud
  não têm essa configuração, e você não pode habilitar o motor por conta própria em
  um serviço desse tipo.
</Note>

## Sintaxe

```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>
  A palavra-chave `SAMPLES` tem um alias `DATA`, e a palavra-chave `METRIC FAMILIES` tem um alias `METRICS`, ambos mantidos por compatibilidade com versões anteriores.
  A definição de uma tabela de uma [version](#schema-versioning) anterior à 4 é gravada com `METRICS`, para que um servidor mais antigo possa lê-la.
</Note>

## Uso

É mais fácil começar com tudo configurado com os valores padrão (é permitido criar uma tabela `TimeSeries` sem especificar uma lista de colunas):

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

Essa tabela pode ser usada com os seguintes protocolos (uma porta deve ser atribuída na configuração do servidor):

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

### Colunas externas

As colunas de uma tabela TimeSeries são geradas automaticamente. São colunas externas: não armazenam dados, apenas fornecem a interface para SELECT/INSERT. Os dados reais são armazenados em [tabelas de destino](#target-tables). Aqui está a lista das colunas externas:

| Nome | Tipo | Descrição |
| - | - | - |
| `metric_name` | `String` | O nome da métrica |
| `tags` | `Map(String, String)` | map de tags (labels) da série temporal |
| `samples` | `Array(Tuple(DateTime64(3), Float64))` por padrão | Array de pares (timestamp, valor) de uma série temporal. Os tipos de elemento do timestamp e do escalar da tupla podem ser derivados da declaração `INNER COLUMNS` das amostras (consulte [Especificando colunas externas](#specifying-outer-columns)). A coluna é denominada `time_series` nas tabelas da [versão](#schema-versioning) 2 e anteriores |
| `metric_family` | `String` | O nome da família de métricas (para os metadados das métricas) |
| `type` | `String` | O tipo da métrica (por exemplo, "counter", "gauge") |
| `unit` | `String` | A unidade da métrica |
| `help` | `String` | A descrição da métrica |

Exemplo:

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

É permitido que `metric_name` fique vazio na inserção; isso significa que o nome da métrica é especificado em `tags`, em `__name__`, por exemplo:

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

Para inserir os metadados das métricas, insira nas colunas `metric_family`, `type`, `unit` e `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')
```

### Especificando colunas externas

A coluna externa `samples` pode ser listada explicitamente em uma instrução `CREATE TABLE` para substituir seu tipo padrão `Array(Tuple(DateTime64(3), Float64))` (seu nome antigo, `time_series`, também é aceito). O ClickHouse extrai, da tupla, os tipos de `timestamp` e do valor escalar e os propaga para a tabela samples:

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

Isso equivale a declarar diretamente, na cláusula `INNER COLUMNS` de samples, os tipos das colunas de timestamp e valor:

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

Se ambas as formas forem usadas na mesma instrução `CREATE TABLE`, os tipos declarados deverão coincidir.

## Tabelas de destino

Uma tabela `TimeSeries` não armazena dados próprios; tudo é armazenado em suas tabelas de destino.
Isso é semelhante ao funcionamento de uma [visão materializada](/pt-BR/reference/statements/create/view#materialized-view),
com a diferença de que uma visão materializada tem uma tabela de destino,
enquanto uma tabela `TimeSeries` tem três tabelas de destino obrigatórias chamadas [samples](#samples-table), [tags](#tags-table) e [metric families](#metric-families-table),
e uma tabela de destino opcional [amostras recentes](#recent-samples-table), que vem habilitada por padrão
(consulte a configuração [recent\_samples\_ttl\_seconds](#settings)).

As tabelas de destino podem ser especificadas explicitamente na consulta `CREATE TABLE`
ou o motor de tabela `TimeSeries` pode gerar automaticamente tabelas de destino internas.

As linhas inseridas em uma tabela `TimeSeries` são transformadas, divididas em blocos e inseridas nessas tabelas de destino.

As tabelas de destino são as seguintes:

### Tabela *samples*

A tabela *samples* contém séries temporais associadas a um identificador.

A tabela *samples* deve ter as seguintes colunas:

| Nome | Obrigatória? | Tipo padrão | Tipos possíveis | Descrição |
| - | - | - | - | - |
| `id` | \[x] | `Tuple(UInt64, LowCardinality(UUID))` | qualquer | Identifica uma combinação de nomes de métricas e tags |
| `timestamp` | \[x] | `DateTime64(3)` | `DateTime64(X)` | Um ponto no tempo |
| `value` | \[x] | `Float64` | `Float32` ou `Float64` | Um valor associado ao `timestamp` |

As colunas que o motor cria por conta própria recebem codecs de compressão de séries temporais:
`timestamp CODEC(Delta, T64, ZSTD(3))` e `value CODEC(ALP, ZSTD(3))`. Timestamps quase monotônicos mal
são comprimidos por codecs genéricos e podem, caso contrário, dominar o tamanho em disco da tabela samples.
O motor habilita `ALP` para suas tabelas internas samples e amostras recentes sem exigir que `enable_alp_codec` seja definido.
Consulte também [Ajustando os tipos das colunas](#adjusting-column-types).

### Tabela de amostras recentes

A tabela de *amostras recentes* é opcional e está habilitada por padrão (consulte a configuração [recent\_samples\_ttl\_seconds](#settings);
defini-la como zero desabilita a tabela). Ela contém uma cópia das amostras mais recentes que o TTL definido por essa configuração
e deve ter as mesmas colunas que a tabela [samples](#samples-table).
A coluna `timestamp` gerada usa `CODEC(Delta, T64, ZSTD(3))`,
e a coluna `value` gerada usa `CODEC(ALP, ZSTD(3))`.

Toda amostra inserida é gravada tanto na tabela samples quanto na tabela de amostras recentes.
As consultas cujo intervalo de tempo se encaixa na janela do TTL leem da tabela de amostras recentes em vez da tabela samples principal,
já que ela é muito menor (esse comportamento pode ser desabilitado com a configuração de nível de consulta `time_series_prefer_recent_samples_table`).

O TTL da tabela interna de amostras recentes é sempre derivado da configuração [recent\_samples\_ttl\_seconds](#settings).

### Tabela de tags

A tabela *tags* contém identificadores calculados para cada combinação de nome de métrica e tags.

A tabela *tags* deve ter as colunas:

| Nome | Obrigatório? | Tipo padrão | Tipos possíveis | Descrição |
| - | - | - | - | - |
| `id` | \[x] | `Tuple(UInt64, LowCardinality(UUID))` | qualquer tipo (deve corresponder ao tipo de `id` na tabela [samples](#samples-table)) | Um `id` identifica uma combinação de nome de métrica e tags. A expressão DEFAULT especifica como calcular esse identificador |
| `metric_name` | \[x] | `LowCardinality(String)` | `String` ou `LowCardinality(String)` | O nome de uma métrica |
| `<tag_value_column>` | \[ ] | `String` | `String` ou `LowCardinality(String)` ou `LowCardinality(Nullable(String))` | O valor de uma tag específica; o nome da tag e o nome da coluna correspondente são especificados na configuração [tags\_to\_columns](#settings) |
| `tags` | \[x] | `Map(LowCardinality(String), String)` | `Map(String, String)` ou `Map(LowCardinality(String), String)` ou `Map(LowCardinality(String), LowCardinality(String))` | map de todas as tags, incluindo a tag `__name__`, que contém o nome de uma métrica, e as tags com nomes listados na configuração [tags\_to\_columns](#settings). As tabelas criadas por versões mais antigas do ClickHouse armazenavam nesta coluna apenas as tags sem colunas dedicadas e sem o nome da métrica; a leitura lida com ambos os casos |
| `min_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` ou `Nullable(DateTime64(X))` | timestamp mínimo da série temporal com esse `id`. A coluna é criada se [store\_min\_time\_and\_max\_time](#settings) for `true` |
| `max_time` | \[ ] | `Nullable(DateTime64(3))` | `DateTime64(X)` ou `Nullable(DateTime64(X))` | timestamp máximo da série temporal com esse `id`. A coluna é criada se [store\_min\_time\_and\_max\_time](#settings) for `true` |

Novas tabelas internas de tags da [versão](#schema-versioning) 5 e posteriores com um motor da família `MergeTree` têm um índice de texto invertido em `tags`:
`INDEX tags_idx tags TYPE text(tokenizer = 'keyValuePairs')`. Ele acelera correspondências exatas de rótulos, como
`{job="api"}` em PromQL, consultando a chave e o valor em conjunto. Comparações com uma string vazia também
correspondem a rótulos ausentes e não usam esse índice.

Índices explícitos declarados em `TAGS INNER COLUMNS` substituem o índice padrão. As tabelas existentes e as
tabelas de tags externas mantêm seus índices; adicione e materialize o índice na tabela de destino das tags para habilitá-lo.

### Tabela de famílias de métricas

A tabela *metric families* contém algumas informações sobre as famílias de métricas coletadas, os tipos dessas famílias de métricas e suas descrições.
Uma família de métricas é um grupo de métricas com o mesmo nome (a tag `__name__`) e o mesmo tipo; por exemplo, um histograma é uma família de métricas composta por várias métricas.

A tabela *metric families* deve conter as colunas:

| Nome | Obrigatória? | Tipo padrão | Tipos possíveis | Descrição |
| - | - | - | - | - |
| `metric_family_name` | \[x] | `String` | `String` ou `LowCardinality(String)` | O nome de uma família de métricas |
| `type` | \[x] | `LowCardinality(String)` | `String` ou `LowCardinality(String)` | O tipo de uma família de métricas, um de "counter", "gauge", "summary", "stateset", "histogram", "gaugehistogram" |
| `unit` | \[x] | `LowCardinality(String)` | `String` ou `LowCardinality(String)` | A unidade usada em uma métrica |
| `help` | \[x] | `String` | `String` ou `LowCardinality(String)` | A descrição de uma métrica |

## Criação

Existem várias maneiras de criar uma tabela com o motor de tabela `TimeSeries`.
A instrução mais simples

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

na verdade criará a seguinte tabela (você pode verificar isso executando `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
```

Portanto, as colunas foram geradas automaticamente e também existem quatro tabelas de destino internas com suas próprias definições de colunas
armazenadas nas cláusulas `INNER COLUMNS`. A configuração `recent_samples_ttl_seconds` foi gravada na cláusula `SETTINGS`
com seu valor padrão: essa configuração define o TTL da tabela de amostras recentes, de modo que seu valor efetivo é fixado na criação.
Além disso, a versão de schema mais recente foi fixada na configuração `version` (consulte [Versionamento de schema](#schema-versioning)).

As tabelas de destino internas têm nomes como `.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`
e cada tabela de destino tem seu próprio conjunto de colunas:

```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
```

## Criar uma tabela AS a partir de uma tabela existente

A instrução `CREATE TABLE new_table AS existing_table` cria uma tabela `TimeSeries` configurada como `existing_table`,
que deve ser uma tabela `TimeSeries`. Os destinos externos de `existing_table` não são copiados: a própria instrução deve declarar
esses destinos.

A instrução copia de `existing_table`:

* a cláusula `SETTINGS`, exceto `version`: a nova tabela sempre recebe a versão mais recente. As configurações especificadas na instrução
  são mescladas às copiadas pelo nome; portanto, uma configuração especificada prevalece sobre a copiada, e `name = DEFAULT`
  redefine uma configuração copiada para o valor padrão;
* as cláusulas `INNER COLUMNS` e `INNER ENGINE` de cada tabela interna. Colunas personalizadas (por exemplo, colunas extras ou colunas
  com um codec ou uma expressão DEFAULT) e partes personalizadas do motor (por exemplo, um motor com argumentos, uma chave de ordenação personalizada
  ou uma configuração do motor) são mantidas; as demais colunas e partes do motor são ajustadas às configurações da nova tabela para que,
  por exemplo, `tags_to_columns`, `aggregate_min_time_and_max_time` ou `tags_index_granularity` especificadas na instrução tenham efeito.

Os tipos das colunas `id`, de timestamp e de valor, bem como o tipo de replicação dos motores internos (`MergeTree`,
`ReplicatedMergeTree` ou `SharedMergeTree`), também são obtidos de `existing_table`, a menos que a própria instrução os declare.
A lista de colunas externas é regenerada, não copiada.

Uma tabela criada por uma versão mais antiga do ClickHouse pode ser usada como `existing_table`: a nova tabela recebe a
estrutura atual, por exemplo, o tipo `id` atual e a expressão padrão de identificador.

## Ajustando os tipos das colunas

Você pode ajustar os tipos das colunas nas tabelas de destino internas usando a cláusula `INNER COLUMNS`. Por exemplo, para armazenar timestamps em microssegundos e valores como `Float32`, use:

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

Especificar colunas internas sem codecs significa usar o codec padrão para elas:

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

## A coluna `id`

A coluna `id` contém identificadores; cada identificador é calculado com base em uma combinação de nome de métrica e tags.
O tipo e a expressão `DEFAULT` usados para gerar identificadores podem ser personalizados por meio da cláusula `TAGS INNER COLUMNS`:

```sql theme={null}
CREATE TABLE my_table ENGINE=TimeSeries
TAGS INNER COLUMNS (id UInt64 DEFAULT sipHash64(tags))
```

A coluna `id` pode ser de qualquer tipo comparável que não seja Nullable. Os tipos de `id` declarados nas tabelas internas `samples` e `tags` devem corresponder.

Se nenhuma expressão `DEFAULT` for fornecida para a coluna `id` e a configuração `id_generator` não estiver definida, ClickHouse escolherá a expressão `DEFAULT` automaticamente com base no tipo de `id`, mas apenas se o tipo de `id` for um dos seguintes: `UUID`, `UInt64`, `UInt128`, `FixedString(16)`, os mesmos tipos encapsulados em `LowCardinality` ou uma tupla de dois desses tipos. Para essa tupla, a expressão escolhida automaticamente calcula um hash do nome de métrica no primeiro componente e um hash de todas as tags no segundo componente.

Um tipo de identificador `LowCardinality`, por exemplo `Tuple(UInt64, LowCardinality(UUID))`, mantém os identificadores codificados por dicionário: a tabela `samples` armazena pequenos dicionários por bloco com dictionary indexes em vez de repetir o identificador completo em cada linha, o que reduz a quantidade de dados lidos pelas consultas.

A configuração `id_generator` oferece a mesma personalização sem usar a cláusula `INNER COLUMNS`:

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

Se essa configuração estiver definida, ela será usada para gerar o `id`, mesmo que o `DEFAULT` da coluna contenha uma expressão diferente.

O tipo da coluna `id` também pode ser especificado na configuração `id_type` em vez da cláusula `INNER COLUMNS`:

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

Quando a configuração `id_generator` está definida, a configuração `id_type` é registrada automaticamente no momento do `CREATE`, de modo que a definição preserva o tipo para o qual a expressão foi escrita.

## A coluna `tags`

A coluna `tags` contém todas as tags de uma série temporal, incluindo a tag `__name__` com o nome de uma métrica.

A configuração `tags_to_columns` permite especificar que uma tag específica também deve ser armazenada em uma coluna separada
além do map dentro da coluna `tags`:

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

Esta instrução adicionará as colunas `instance` e `job` à tabela de destino interna de [tags](#tags-table).
Os valores das tags `instance` e `job` serão armazenados tanto nessas colunas quanto na coluna `tags`.

<Note>
  Nas tabelas criadas por versões mais antigas do ClickHouse, a coluna `tags` contém apenas as tags sem colunas
  dedicadas e sem o nome da métrica, e a coluna `all_tags` é uma coluna efêmera preenchida na inserção
  com todas as tags, exceto o nome da métrica.
</Note>

## Motores de tabela das tabelas de destino internas

Por padrão, as tabelas de destino internas usam os seguintes motores de tabela:

* a tabela [samples](#samples-table) usa [MergeTree](/pt-BR/reference/engines/table-engines/mergetree-family/mergetree);
* a tabela [amostras recentes](#recent-samples-table) usa [MergeTree](/pt-BR/reference/engines/table-engines/mergetree-family/mergetree) particionada em buckets de 5 horas (consulte a configuração [recent\_samples\_partition\_by](#settings)) com um `TTL` derivado da
  configuração [recent\_samples\_ttl\_seconds](#settings) e com `ttl_only_drop_parts` habilitado, de modo que as partes expiradas são removidas por inteiro;
* a tabela [tags](#tags-table) usa [AggregatingMergeTree](/pt-BR/reference/engines/table-engines/mergetree-family/aggregatingmergetree) porque os mesmos dados costumam ser inseridos várias vezes nessa tabela, então precisamos de uma forma
  de remover duplicatas, além de ser necessário fazer agregação para as colunas `min_time` e `max_time`;
* a tabela [famílias de métricas](#metric-families-table) usa [ReplacingMergeTree](/pt-BR/reference/engines/table-engines/mergetree-family/replacingmergetree) porque os mesmos dados costumam ser inseridos várias vezes nessa tabela, então precisamos de uma forma
  de remover duplicatas.

A família de motores das tabelas internas geradas segue a configuração de nível de consulta `default_table_engine`:
com `default_table_engine = ReplicatedMergeTree` ou `SharedMergeTree`, as tabelas internas usam os motores
`Replicated` ou `Shared` correspondentes. Com `default_table_engine = None` (ou qualquer outro valor), os motores das tabelas internas
devem ser especificados explicitamente.

Todas as tabelas internas devem ter o mesmo tipo de replicação: se uma delas for replicada (ou compartilhada), as demais tabelas
internas também devem ser replicadas (ou compartilhadas); caso contrário, seus conteúdos divergiriam entre as réplicas. Por exemplo,
declarar `SAMPLES INNER ENGINE = ReplicatedMergeTree(...)` exige que os demais motores internos também sejam replicados —
seja declarados explicitamente ou gerados com `default_table_engine = ReplicatedMergeTree`.

Outros motores de tabela também podem ser usados nas tabelas de destino internas, caso isso seja especificado:

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

A tabela [tags](#tags-table) mantém as colunas de tag (e o Map `tags`) fora de sua chave de ordenação,
o que `AggregatingMergeTree` rejeita por padrão (consulte [`allow_dimensions_outside_sorting_key`](/pt-BR/reference/engines/table-engines/mergetree-family/aggregatingmergetree)).
Isso é seguro aqui porque essas colunas dependem funcionalmente de `id`, que faz parte da chave de ordenação, portanto todas as
linhas que uma mesclagem em segundo plano combina compartilham os mesmos valores. Quando a tabela interna de tags é gerada ou seu
motor é especificado inline, como acima, `TimeSeries` define `allow_dimensions_outside_sorting_key = 1` nela automaticamente;
para uma tabela [externa](#external-target-tables) de tags com agregação criada manualmente, você deve definir isso por conta própria.

## Tabelas de destino externas

É possível fazer com que uma tabela `TimeSeries` use uma tabela criada manualmente:

```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;
```

Uma tabela externa também pode ser usada como destino de [amostras recentes](#recent-samples-table) (a cláusula `RECENT SAMPLES my_recent_samples_table`).
Essa tabela deve ter as mesmas colunas de uma tabela samples externa e deve reter pelo menos
[recent\_samples\_ttl\_seconds](#settings) segundos de dados, o que é responsabilidade do usuário.

Os tipos de coluna das tabelas externas (`id`, `timestamp`, `value` e os `<tag_value_column>` listados em [`tags_to_columns`](#settings)) devem corresponder aos que a tabela `TimeSeries` geraria internamente (consulte [Tabela samples](#samples-table), [Tabela de Tags](#tags-table) e [Tabela de famílias de métricas](#metric-families-table) para as restrições de tipo). Incompatibilidades de tipo são informadas no momento do `CREATE`.

O tipo da coluna `id` de uma tabela de tags externa e a expressão que gera os identificadores são registrados nas configurações [`id_type`](#settings) e [`id_generator`](#settings) no momento do `CREATE` (a partir da [versão](#schema-versioning) 2), de modo que a definição da tabela `TimeSeries` os mantém: por exemplo, `CREATE TABLE ... AS my_table` lê o tipo de `id` a partir da definição de `my_table` sem ler suas tabelas de destino externas. Se a configuração `id_generator` não for especificada, ela é definida como o `DEFAULT` declarado na coluna `id` da tabela externa (se houver) ou, caso contrário, como o gerador canônico derivado do tipo de `id`. A expressão registrada é usada para gerar o `id` mesmo que o `DEFAULT` da tabela externa mude posteriormente — consulte [A coluna `id`](#id-column) para mais detalhes.

## Alterando configurações

Duas configurações podem ser alteradas após `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;
```

Observe que alterar `id_generator` quando já existem dados na tabela de tags pode gerar IDs diferentes para a mesma combinação de métrica+tag — as linhas antigas mantêm seus IDs antigos, e as linhas novas usam o novo gerador.

As outras configurações não podem ser alteradas com `ALTER ... MODIFY SETTING`: a maioria delas é incorporada ao esquema das tabelas internas no momento do `CREATE`,
e a configuração `version` é fixada automaticamente no momento do `CREATE` e identifica o próprio esquema (consulte [Versionamento de schema](#schema-versioning)).

## Configurações

Aqui está uma lista de configurações que podem ser especificadas ao definir uma tabela `TimeSeries`:

| Nome | Tipo | Padrão | Descrição |
| - | - | - | - |
| `id_type` | Tipo de dado | depende da coluna `id` | O tipo da coluna `id` das tabelas de destino. Normalmente o tipo é declarado nas cláusulas `INNER COLUMNS` das tabelas internas ou em uma tabela tags [externa](#external-target-tables); a configuração é registrada automaticamente no momento do `CREATE` caso o tipo não seja mantido na definição de outra forma: se o destino de tags for uma tabela externa, ou se a configuração `id_generator` estiver definida. A configuração também pode ser especificada explicitamente em vez de `TAGS INNER COLUMNS (id <type>)`. Requer que `version` seja pelo menos 2 |
| `id_generator` | Expression | depende do tipo de `id` | Expressão que calcula o identificador (fingerprint) de uma série temporal a partir de suas tags. Se não for definida, a expressão padrão da coluna `id` será usada. Se a expressão padrão da coluna `id` também não estiver definida, a expressão será escolhida automaticamente. Para uma tabela tags externa, a configuração é registrada automaticamente no momento do `CREATE` se `version` for pelo menos 2 (consulte [Tabelas de destino externas](#external-target-tables)) |
| `tags_to_columns` | Map | {} | Map que especifica quais tags devem ser colocadas em colunas separadas na tabela [tags](#tags-table). Sintaxe: `{'tag1': 'column1', 'tag2' : column2, ...}` |
| `use_all_tags_column_to_generate_id` | Bool | false | Configuração obsoleta, não faz nada |
| `store_min_time_and_max_time` | Bool | true | Se definido como true, a tabela armazenará `min_time` e `max_time` para cada série temporal |
| `aggregate_min_time_and_max_time` | Bool | true | Ao criar uma tabela `tags` interna de destino, esta opção permite usar `SimpleAggregateFunction(min, Nullable(DateTime64(3)))` em vez de apenas `Nullable(DateTime64(3))` como tipo da coluna `min_time`, e o mesmo para a coluna `max_time` |
| `filter_by_min_time_and_max_time` | Bool | true | Se definido como true, a tabela usará as colunas `min_time` e `max_time` para filtrar séries temporais |
| `samples_index_granularity` | UInt64 | 32768 | Define `index_granularity` da tabela [samples](#samples-table) interna. Quando definido explicitamente, substitui `index_granularity` da declaração do motor. Ignorado para uma tabela samples externa e um motor que não seja MergeTree |
| `recent_samples_ttl_seconds` | UInt64 | 345600 | Retenção da tabela de destino adicional `amostras recentes`, na qual cada amostra inserida também é gravada. Uma tabela interna de amostras recentes sempre recebe `TTL toDateTime(timestamp) + toIntervalSecond(recent_samples_ttl_seconds)` derivado desta configuração (substituindo qualquer TTL da declaração do motor); uma tabela externa de amostras recentes deve reter pelo menos essa quantidade de segundos de dados. Consultas cujo intervalo de tempo está dentro da janela de TTL priorizam a tabela de amostras recentes em vez da tabela principal de amostras (consulte a configuração no nível da consulta `time_series_prefer_recent_samples_table`). O padrão é de 4 dias; o valor efetivo é fixado na definição da tabela no momento do CREATE. Defina como 0 para desabilitar a tabela de amostras recentes |
| `recent_samples_partition_by` | Expression | `toStartOfInterval(toDateTime(timestamp), toIntervalHour(5))` | Chave de partição da tabela interna `amostras recentes`, por exemplo, `toStartOfHour(timestamp)`. Quando definida explicitamente, substitui a chave de partição da declaração do motor; se nenhuma das duas for definida, é usada uma partição a cada 5 horas. Ignorado para uma tabela externa de amostras recentes. Requer que `recent_samples_ttl_seconds` seja diferente de zero |
| `recent_samples_index_granularity` | UInt64 | 8192 | Define `index_granularity` da tabela interna `amostras recentes`. Quando definido explicitamente, substitui `index_granularity` da declaração do motor. Ignorado para uma tabela externa de amostras recentes e um motor que não seja MergeTree. Requer que `recent_samples_ttl_seconds` seja diferente de zero |
| `tags_index_granularity` | UInt64 | 8192 | Define `index_granularity` da tabela [tags](#tags-table) interna. Quando definido explicitamente, substitui `index_granularity` da declaração do motor. Ignorado para uma tabela tags externa e um motor que não seja MergeTree |
| `version` | UInt64 | 5 | A versão da tabela: identifica o conjunto de tabelas de destino e sua estrutura. A versão é fixada automaticamente quando uma tabela é criada e não pode ser alterada depois; normalmente ela deve ser omitida na consulta `CREATE TABLE` (consulte [Versionamento de schema](#schema-versioning)) |

## Versionamento de schema

O motor de tabela `TimeSeries` e a camada de execução de PromQL estão em desenvolvimento ativo:
o conjunto de tabelas de destino e sua estrutura podem mudar entre versões do ClickHouse.
Para tornar essas mudanças detectáveis, cada tabela `TimeSeries` armazena sua versão na configuração [version](#settings).
A versão é fixada automaticamente na consulta `CREATE` no momento da criação da tabela — seu valor é a versão mais recente conhecida pelo servidor (atualmente 5) —,
persiste nos metadados da tabela e não pode ser alterada por `ALTER`. Tabelas criadas antes da introdução dessa configuração são consideradas como versão 0.
Normalmente, basta omitir a configuração na consulta `CREATE TABLE` — assim a tabela recebe a versão mais recente.
Um `version` explícito é aceito se o servidor der suporte a essa versão; nesse caso, a tabela é definida da forma como aquela versão a define (consulte [Histórico de versões](#version-history)).
`CREATE TABLE ... AS other_table` não copia a versão da outra tabela; consulte [Criar uma tabela AS a partir de uma tabela existente](#create-as).

Um servidor dá suporte a um intervalo de versões, e a versão mínima pode variar conforme a operação: leitura com `SELECT`, gravação com `INSERT`
ou com o protocolo remote-write do Prometheus, e avaliação de PromQL (as funções de tabela [prometheusQuery](/pt-BR/reference/functions/table-functions/prometheusQuery),
[prometheusQueryRange](/pt-BR/reference/functions/table-functions/prometheusQueryRange)
e [timeSeriesSelector](/pt-BR/reference/functions/table-functions/timeSeriesSelector),
o dialect `promql` e a API HTTP de consulta do Prometheus):

* Se a versão de uma tabela `TimeSeries` for antiga demais para PromQL, as consultas PromQL sobre ela são rejeitadas. A exceção sugere recriar a tabela:
  crie uma nova tabela `TimeSeries`, copie os dados com uma consulta `INSERT ... SELECT` e substitua a tabela antiga pela nova.
* Se a versão for antiga demais para gravação, as consultas `INSERT` e o protocolo remote-write do Prometheus são rejeitados, enquanto as consultas `SELECT` continuam funcionando.
* Se a versão for antiga demais para o servidor como um todo, toda consulta sobre a tabela (exceto `SHOW CREATE TABLE`, `DETACH` e `DROP`) é rejeitada.

### Histórico de versões

| Versão | Alterações |
| - | - |
| 0 | Tabelas criadas antes da introdução da configuração `version`, incluindo tabelas "prealpha" (que declaravam as colunas das tabelas de destino como [colunas externas](#outer-columns)) e tabelas sem a tabela de [amostras recentes](#recent-samples-table) |
| 1 | A configuração `version` foi introduzida |
| 2 | A configuração [`id_type`](#settings) foi introduzida: uma tabela com uma tabela de tags externa registra o tipo da coluna `id` em `id_type` e a expressão que gera identificadores em [`id_generator`](#settings), de modo que sua definição não dependa da tabela externa. `id_type` também é registrado quando `id_generator` é definido (consulte [A coluna `id`](#id-column)) |
| 3 | A coluna externa `time_series` foi renomeada para `samples` (consulte [Colunas externas](#outer-columns)). As tabelas de versões anteriores mantêm o nome antigo da coluna, e as funções de tabela [prometheusQuery](/pt-BR/reference/functions/table-functions/prometheusQuery) e [prometheusQueryRange](/pt-BR/reference/functions/table-functions/prometheusQueryRange) retornam a coluna com o nome usado pela tabela. Os dados armazenados não foram alterados |
| 4 | A tabela de destino `metrics` foi renomeada para `metric families`: a tabela interna é chamada de `.inner_id.metricfamilies.<uuid>` em vez de `.inner_id.metrics.<uuid>`, e a definição é gravada com a palavra-chave `METRIC FAMILIES` em vez de `METRICS`. Os dados armazenados não foram alterados |
| 5 | Novas tabelas internas de tags com um motor da família `MergeTree` recebem, por padrão, um índice de texto `keyValuePairs` no map `tags` (consulte [Tabela de tags](#tags-table)) |

# Funções

Aqui está uma lista de funções que aceitam uma tabela `TimeSeries` como argumento:

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