一种用于存储时间序列的表引擎,即一组与时间戳和标签 (或标记) 关联的值:
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)]]
关键字 SAMPLES 有一个别名 DATA,保留它是为了保持向后兼容性。
一开始先使用默认设置会更简单 (可以在不指定列列表的情况下创建 TimeSeries 表) :
CREATE TABLE my_table ENGINE=TimeSeries
随后,该表可与以下协议配合使用 (必须在服务器配置中分配端口) :
TimeSeries 表的列会自动生成。这些列属于外部列,不存储任何数据,只为 SELECT/INSERT 提供接口。实际数据存储在目标表中。以下是外部列列表:
| Name | Type | Description |
|---|
metric_name | String | 指标名称 |
tags | Map(String, String) | 时间序列的标签映射 (标记) |
time_series | Array(Tuple(DateTime64(3), Float64)) (默认) | 时间序列的 (timestamp, value) 对数组。该 Tuple 的 timestamp 和 scalar 元素类型可从 samples INNER COLUMNS 声明中推导得出 (参见指定外部列) |
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')
可以在 CREATE TABLE 语句中显式列出外部 time_series 列,以覆盖其默认的 Array(Tuple(DateTime64(3), Float64)) 类型。ClickHouse 会从该元组中提取时间戳类型和值类型,并将它们传递到内部样本表:
CREATE TABLE my_table (time_series Array(Tuple(UInt32, Float32))) ENGINE=TimeSeries
这相当于直接在 samples 的 INNER COLUMNS 子句中声明时间戳列和值列的类型:
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp UInt32, value Float32)
如果在同一条 CREATE TABLE 语句中同时使用这两种形式,则声明的类型必须一致。
TimeSeries 表本身不存储数据,所有数据都保存在其目标表中。
这与 materialized view 的工作方式类似,
区别在于 materialized view 只有一个目标表,
而 TimeSeries 表有三个目标表,分别名为 samples、标签 和 metrics。
这些目标表既可以在 CREATE TABLE 查询中显式指定,
也可以由 TimeSeries 表引擎自动生成内部目标表。
插入 TimeSeries 表的行会被转换、拆分为块,并写入这三个目标表。
目标表如下:
samples 表包含与某个标识符关联的时间序列。
samples 表必须包含以下列:
| 名称 | 必填? | 默认类型 | 可选类型 | 描述 |
|---|
id | [x] | UUID | any | 标识一组指标名称和标签的组合 |
timestamp | [x] | DateTime64(3) | DateTime64(X) | 一个时间点 |
value | [x] | Float64 | Float32 或 Float64 | 与 timestamp 关联的值 |
tags 表包含针对每种指标名称与标签组合计算出的标识符。
tags 表必须包含以下列:
| 名称 | 必填? | 默认类型 | 可能的类型 | 描述 |
|---|
id | [x] | UUID | any (必须与 samples 表中 id 的类型匹配) | id 用于标识一种指标名称与标签的组合。DEFAULT 表达式指定了如何计算该标识符 |
metric_name | [x] | LowCardinality(String) | String 或 LowCardinality(String) | 指标名称 |
<tag_value_column> | [ ] | String | String 或 LowCardinality(String) 或 LowCardinality(Nullable(String)) | 特定标签的值;该标签的名称以及对应列的名称在 tags_to_columns 设置中指定 |
tags | [x] | Map(LowCardinality(String), String) | Map(String, String) 或 Map(LowCardinality(String), String) 或 Map(LowCardinality(String), LowCardinality(String)) | 标签映射,不包括表示指标名称的标签 __name__,也不包括 tags_to_columns 设置中枚举的标签名称 |
all_tags | [ ] | Map(String, String) | Map(String, String) 或 Map(LowCardinality(String), String) 或 Map(LowCardinality(String), LowCardinality(String)) | 临时列,每一行都是一个包含所有标签的映射,仅排除表示指标名称的标签 __name__。该列的唯一用途是在计算 id 时使用 |
min_time | [ ] | Nullable(DateTime64(3)) | DateTime64(X) 或 Nullable(DateTime64(X)) | 具有该 id 的时间序列的最小时间戳。如果 store_min_time_and_max_time 为 true,则会创建此列 |
max_time | [ ] | Nullable(DateTime64(3)) | DateTime64(X) 或 Nullable(DateTime64(X)) | 具有该 id 的时间序列的最大时间戳。如果 store_min_time_and_max_time 为 true,则会创建此列 |
metrics 表包含有关已采集指标、其类型及描述的信息。
metrics 表必须包含以下列:
| 名称 | 必需? | 默认类型 | 可能的类型 | 描述 |
|---|
metric_family_name | [x] | String | String 或 LowCardinality(String) | 指标族的名称 |
type | [x] | LowCardinality(String) | String 或 LowCardinality(String) | 指标族的类型,可为 “counter”、“gauge”、“summary”、“stateset”、“histogram”、“gaugehistogram” 之一 |
unit | [x] | LowCardinality(String) | String 或 LowCardinality(String) | 指标使用的单位 |
help | [x] | String | String 或 LowCardinality(String) | 指标的描述 |
可以通过多种方式使用 TimeSeries 表引擎创建表。
最简单的语句
CREATE TABLE my_table ENGINE=TimeSeries
实际上会创建下列表 (可通过执行 SHOW CREATE TABLE my_table 查看) :
CREATE TABLE my_table
(
`metric_name` String,
`tags` Map(String, String),
`time_series` Array(Tuple(DateTime64(3), Float64)),
`metric_family` String,
`type` String,
`unit` String,
`help` String
)
ENGINE = TimeSeries
SAMPLES INNER COLUMNS
(
`id` UUID,
`timestamp` DateTime64(3),
`value` Float64
)
SAMPLES INNER ENGINE = MergeTree ORDER BY (id, timestamp)
TAGS INNER COLUMNS
(
`id` UUID DEFAULT reinterpretAsUUID(sipHash128(metric_name, all_tags)),
`metric_name` LowCardinality(String),
`tags` Map(LowCardinality(String), String),
`all_tags` Map(String, String) EPHEMERAL,
`min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
`max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3)))
)
TAGS INNER ENGINE = AggregatingMergeTree PRIMARY KEY metric_name ORDER BY (metric_name, id)
METRICS INNER COLUMNS
(
`metric_family_name` String,
`type` LowCardinality(String),
`unit` LowCardinality(String),
`help` String
)
METRICS INNER ENGINE = ReplacingMergeTree ORDER BY metric_family_name
因此,这些列是自动生成的,而且还有三个内部目标表,它们各自的列定义
存储在 INNER COLUMNS 子句中。
内部目标表的名称类似于 .inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx、
.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx、.inner_id.metrics.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
并且每个目标表都有各自的一组列:
CREATE TABLE default.`.inner_id.samples.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
`id` UUID,
`timestamp` DateTime64(3),
`value` Float64
)
ENGINE = MergeTree
ORDER BY (id, timestamp)
CREATE TABLE default.`.inner_id.tags.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
`id` UUID DEFAULT reinterpretAsUUID(sipHash128(metric_name, all_tags)),
`metric_name` LowCardinality(String),
`tags` Map(LowCardinality(String), String),
`all_tags` Map(String, String) EPHEMERAL,
`min_time` SimpleAggregateFunction(min, Nullable(DateTime64(3))),
`max_time` SimpleAggregateFunction(max, Nullable(DateTime64(3)))
)
ENGINE = AggregatingMergeTree
PRIMARY KEY metric_name
ORDER BY (metric_name, id)
CREATE TABLE default.`.inner_id.metrics.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
(
`metric_family_name` String,
`type` LowCardinality(String),
`unit` LowCardinality(String),
`help` String
)
ENGINE = ReplacingMergeTree
ORDER BY metric_family_name
语句 CREATE TABLE new_table AS existing_table 会从 existing_table 复制以下内容:
SETTINGS
- 每种类型的
INNER COLUMNS
- 每种类型的
INNER ENGINE
如果 existing_table 包含外部目标,则不允许使用该语句。
外部列列表会重新生成,而不会被复制。
你可以使用 INNER COLUMNS 子句来调整内部目标表中各列的类型。例如,要将时间戳以微秒存储,并将值存储为 Float32:
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(6), value Float32)
同一子句也可用于指定编解码器及其他列属性:
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES INNER COLUMNS (timestamp DateTime64(3) CODEC(DoubleDelta))
id 列包含标识符;每个标识符都是根据某个指标名称与标签的组合计算得出的。
用于生成标识符的类型和 DEFAULT 表达式可通过 TAGS INNER COLUMNS 子句自定义:
CREATE TABLE my_table ENGINE=TimeSeries
TAGS INNER COLUMNS (id UInt64 DEFAULT sipHash64(metric_name, all_tags))
The id 列的类型必须是 UUID、UInt64、UInt128 或 FixedString(16) 之一。如果未提供 DEFAULT 表达式,ClickHouse 会根据 id 类型自动选择。samples 和 tags 内部表中声明的 id 类型必须保持一致。
id_generator 设置也支持相同的自定义,而无需使用 INNER COLUMNS 子句:
CREATE TABLE my_table ENGINE=TimeSeries
SETTINGS id_generator = 'sipHash64(metric_name, all_tags)'
如果设置了此项,即使该列的 DEFAULT 包含其他表达式,也会用它来生成 id。
有两列包含标签的 Map:tags 和 all_tags。在这个示例中,它们的含义相同;但如果使用 tags_to_columns 设置,
它们也可能不同。此设置允许指定将某个特定标签存储在单独的列中,而不是存储
在 tags 列中的 Map 内:
CREATE TABLE my_table
ENGINE = TimeSeries
SETTINGS tags_to_columns = {'instance': 'instance', 'job': 'job'}
该语句将把 instance 和 job 列添加到内部标签目标表中。
在这种情况下,tags 列将不包含 instance 和 job 这两个标签,
但 all_tags 列会包含它们。all_tags 列是临时列,其唯一用途是用于 id 列的 DEFAULT 表达式
中。
默认情况下,内部目标表使用以下表引擎:
如果指定了其他表引擎,内部目标表也可以使用它们:
CREATE TABLE my_table ENGINE=TimeSeries
SAMPLES ENGINE=ReplicatedMergeTree
TAGS ENGINE=ReplicatedAggregatingMergeTree
METRICS ENGINE=ReplicatedReplacingMergeTree
可以让 TimeSeries 表使用手动创建的目标表:
CREATE TABLE samples_for_my_table
(
`id` UUID,
`timestamp` DateTime64(3),
`value` Float64
)
ENGINE = MergeTree
ORDER BY (id, timestamp);
CREATE TABLE tags_for_my_table ...
CREATE TABLE metrics_for_my_table ...
CREATE TABLE my_table ENGINE=TimeSeries SAMPLES samples_for_my_table TAGS tags_for_my_table METRICS metrics_for_my_table;
外部表的列类型 (id、timestamp、value,以及 tags_to_columns 中列出的各个 <tag_value_column>) 必须与 TimeSeries 表原本会在内部生成的类型一致 (类型约束请参见 Samples 表、标签表 和 指标表) 。类型不匹配会在 CREATE 时报告。
外部标签目标的 id 生成器表达式会在 INSERT 时按以下顺序解析:先是 id_generator 设置 (如果已设置) ,然后是外部表 id 列上声明的 DEFAULT (如果有) ,最后是根据 id 类型派生出的规范生成器) 。因此,该设置会覆盖外部表上声明的任何 DEFAULT——详见 The id column。
执行 CREATE 后,可更改以下两个设置:
id_generator
filter_by_min_time_and_max_time
ALTER TABLE my_table MODIFY SETTING id_generator = 'sipHash64(metric_name, all_tags)';
ALTER TABLE my_table MODIFY SETTING filter_by_min_time_and_max_time = 0;
请注意,如果在标签表中已有数据后更改 id_generator,同一 metric+tag 组合可能会生成不同的 ID——旧行会保留原来的 ID,新行则会使用新的生成器。
其他设置不能通过 ALTER ... MODIFY SETTING 更改,因为它们在 CREATE 时就已经固化在内部表的 schema 中。
以下列出了在定义 TimeSeries 表时可指定的设置:
| 名称 | 类型 | 默认值 | 说明 |
|---|
id_generator | 表达式 | 取决于 id 类型 | 根据时间序列的标签计算其标识符 (指纹) 的表达式。如果未设置,则使用 id 列的默认表达式。如果 id 列的默认表达式也未设置,则会自动选择该表达式 |
tags_to_columns | Map | 指定哪些标签应映射到 标签 表中的独立列。语法:{'tag1': 'column1', 'tag2' : column2, ...} | |
use_all_tags_column_to_generate_id | Bool | true | 在生成用于计算时间序列标识符的表达式时,此标志会启用在计算中使用 all_tags 列 |
store_min_time_and_max_time | Bool | true | 如果设置为 true,则该表会为每个时间序列存储 min_time 和 max_time |
aggregate_min_time_and_max_time | Bool | true | 创建内部目标 tags 表时,此标志会启用将 min_time 列的类型设为 SimpleAggregateFunction(min, Nullable(DateTime64(3))),而不是仅使用 Nullable(DateTime64(3));max_time 列同样如此 |
filter_by_min_time_and_max_time | Bool | true | 如果设置为 true,则该表会使用 min_time 和 max_time 列来过滤时间序列 |
以下列出了支持将 TimeSeries 表作为参数的函数: