Skip to main content
A table engine storing time series, i.e. a set of values associated with timestamps and tags (or labels):
This is an experimental feature that may change in backwards-incompatible ways in the future releases. Enable usage of the TimeSeries table engine with allow_experimental_time_series_table setting. Input the command set allow_experimental_time_series_table = 1.

Syntax

Usage

It’s easier to start with everything set by default (it’s allowed to create a TimeSeries table without specifying a list of columns):
Then this table can be used with the following protocols (a port must be assigned in the server configuration):

Target tables

A TimeSeries table doesn’t have its own data, everything is stored in its target tables. This is similar to how a materialized view works, with the difference that a materialized view has one target table whereas a TimeSeries table has three target tables named data, tags, and metrics. The target tables can be either specified explicitly in the CREATE TABLE query or the TimeSeries table engine can generate inner target tables automatically. The target tables are the following:

Data table

The data table contains time series associated with some identifier. The data table must have columns:

Tags table

The tags table contains identifiers calculated for each combination of a metric name and tags. The tags table must have columns:

Metrics table

The metrics table contains some information about metrics been collected, the types of those metrics and their descriptions. The metrics table must have columns: Any row inserted into a TimeSeries table will be in fact stored in those three target tables. A TimeSeries table contains all those columns from the data, tags, metrics tables.

Creation

There are multiple ways to create a table with the TimeSeries table engine. The simplest statement
will actually create the following table (you can see that by executing SHOW CREATE TABLE my_table):
So the columns were generated automatically and also there are three inner UUIDs in this statement - one per each inner target table that was created. (Inner UUIDs are not shown normally until setting show_table_uuid_in_table_create_query_if_not_nil is set.) Inner target tables have names like .inner_id.data.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, .inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, .inner_id.metrics.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and each target table has columns which is a subset of the columns of the main TimeSeries table:

Adjusting types of columns

You can adjust the types of almost any column of the inner target tables by specifying them explicitly while defining the main table. For example,
will make the inner data table store timestamp in microseconds instead of milliseconds:

The id column

The id column contains identifiers, every identifier is calculated for a combination of a metric name and tags. The DEFAULT expression for the id column is an expression which will be used to calculate such identifiers. Both the type of the id column and that expression can be adjusted by specifying them explicitly:

The tags and all_tags columns

There are two columns containing maps of tags - tags and all_tags. In this example they mean the same, however they can be different if setting tags_to_columns is used. This setting allows to specify that a specific tag should be stored in a separate column instead of storing in a map inside the tags column:
This statement will add columns:
to the definition of both my_table and its inner tags target table. In this case the tags column will not contain tags instance and job, but the all_tags column will contain them. The all_tags column is ephemeral and its only purpose to be used in the DEFAULT expression for the id column. The types of columns can be adjusted by specifying them explicitly:

Table engines of inner target tables

By default inner target tables use the following table engines:
  • the data table uses MergeTree;
  • the tags table uses AggregatingMergeTree because the same data is often inserted multiple times to this table so we need a way to remove duplicates, and also because it’s required to do aggregation for columns min_time and max_time;
  • the metrics table uses ReplacingMergeTree because the same data is often inserted multiple times to this table so we need a way to remove duplicates.
Other table engines also can be used for inner target tables if it’s specified so:

External target tables

It’s possible to make a TimeSeries table use a manually created table:

Settings

Here is a list of settings which can be specified while defining a TimeSeries table: Here is a list of functions supporting a TimeSeries table as an argument:
Last modified on June 12, 2026