TimescaleDB核心概念(下)(翻译整理)
内容概览
聚合操作
扩展 TimescaleDB
分布式超表
压缩
聚合操作
涉及大量时间序列数据的聚合查询 ( min()
, max()
, avg()
...) 可能需要很长时间来计算,因为系统需要在每次查询执行时扫描大量数据。为了使此类查询更快,连续聚合允许具体化计算的聚合,同时还提供了在底层源数据更改时以低开销连续保持它们新的方法。
连续聚合有点类似于 PostgreSQL 的 物化视图,但与物化视图不同的是,连续聚合可以连续和增量刷新。刷新可以手动完成,也可以通过在后台运行的策略完成,并且可以覆盖整个连续聚合或仅覆盖特定时间范围。在任何一种情况下,刷新只会重新计算自上次刷新以来已更改的聚合存储桶。
例子
作为一个快速的介绍性示例,让我们创建一个 conditions包含设备温度数据的超表和一个用于计算每小时平均温度、低温度和高温度的连续聚合。首先创建超表并用一些数据填充它:
CREATE TABLE conditions (
time TIMESTAMPTZ NOT NULL,
device INTEGER NOT NULL,
temperature FLOAT NOT NULL,
PRIMARY KEY(time, device)
);
SELECT * FROM create_hypertable('conditions', 'time', 'device', 3);
INSERT INTO conditions
SELECT time, (random()*30)::int, random()*80 - 40
FROM generate_series(TIMESTAMP '2020-01-01 00:00:00',
TIMESTAMP '2020-06-01 00:00:00',
INTERVAL '10 min') AS time;
然后,您可以创建一个连续聚合视图来计算每小时平均温度、低温度和高温度:
CREATE MATERIALIZED VIEW conditions_summary_hourly
WITH (timescaledb.continuous) AS
SELECT device,
time_bucket(INTERVAL '1 hour', time) AS bucket,
AVG(temperature),
MAX(temperature),
MIN(temperature)
FROM conditions
GROUP BY device, bucket;
后,您应该添加一个策略以确保定期刷新连续聚合。
SELECT add_continuous_aggregate_policy('conditions_summary_hourly',
start_offset => INTERVAL '1 month',
end_offset => INTERVAL '1 h',
schedule_interval => INTERVAL '1 h');
在这种情况下,连续聚合每小时刷新一次,并刷新上个月的数据。
您现在可以SELECT
在连续聚合上运行正常,它会为您提供聚合数据,例如,选择设备 1 在前三个月的每小时平均值:
SELECT bucket, avg
FROM conditions_summary_hourly
WHERE device = 1 AND bucket BETWEEN '2020-01-01' AND '2020-03-31'
ORDER BY bucket;
大多数可以由 PostgreSQL 并行化的聚合函数都支持连续聚合,其中包括普通聚合,如SUM
和AVG
。但是,使用ORDER BY
和的聚合DISTINCT
不能与连续聚合一起使用,因为 PostgreSQL 无法并行化它们。此外,尽管可以并行化,但TimescaleDB 连续聚合当前不支持该FILTER
子句(不要与 混淆 ),但我们可能会在未来版本中添加对此的支持。
实时聚合
默认情况下,对连续聚合的查询使用实时聚合(在 TimescaleDB 1.7 中引入)将物化聚合与源超表中的新数据相结合。通过以这种方式结合原始数据和物化数据,实时聚合可产生准确和新的结果,同时仍受益于大部分结果的预先计算的聚合。
实时聚合是任何新的连续聚合的默认行为。要禁用实时聚合并仅显示物化数据,请 timescaledb.materialized_only=true
在创建连续聚合视图时添加该参数,或使用 将其设置在现有连续聚合上 ALTER MATERIALIZED VIEW
。
使用连续聚合策略自动刷新
通过使用连续聚合策略,连续聚合可以在后一个桶的时间宽度内保持新。策略允许您在按计划更新的连续聚合中保持指定的时间窗口。这提供了执行以下操作的能力:
使连续聚合和超表同步,即使从超表中删除数据,或者
从超表中删除源数据时,将聚合数据保留在连续聚合中。
从 TimescaleDB 2.0 开始,也可以使用 refresh_continuous_aggregate
. 使用此 TimescaleDB 功能使用户能够拥有两全其美的能力:自动刷新近的数据,并通过回填过程对可能在历史上进一步发生的时间范围进行有针对性的更新。使用这两种工具来保持连续聚合是新的,提供了很好的控制和灵活性!
时间序列数据的一个内在部分是新数据不断积累,而旧数据很少更新,如果有的话,数据的相关性会随着时间的推移而减少。因此,通常希望删除旧数据以节省磁盘空间。
例如,如果您有一个超表定义conditions
,可以将原始数据收集到一天的数据块中:
CREATE TABLE conditions(
time TIMESTAMPTZ NOT NULL,
device INTEGER,
temperature FLOAT
);
SELECT * FROM create_hypertable('conditions', 'time',
chunk_time_interval => INTERVAL '1 day');
如果您收集了大量数据并意识到您从未真正使用超过 30 天的原始数据,您可能希望从conditions
.
DELETE
但是,如果使用标准命令逐行删除表中的大量数据,则代价高昂且速度缓慢。相反,TimescaleDB 提供了一种功能drop_chunks
,可以快速删除块粒度的数据,而不会产生相同的开销。
例如:
SELECT drop_chunks('conditions', INTERVAL '24 hours');
这会从超表conditions
中删除仅 包含早于此持续时间的数据的所有块,并且不会删除块中的任何单个数据行。
TimescaleDB 还包括一个后台作业调度框架,用于自动执行数据管理任务,例如启用简单的数据保留策略。借助策略,您可以在每个超表上设置数据保留标准,并允许 TimescaleDB 根据需要删除数据。
值得注意的是,连续聚合也是有效的目标保留策略。
用户定义的动作
用户定义的操作允许您在 TimescaleDB 中按计划运行以您选择的语言实现的功能和过程。这允许自动执行现有策略未涵盖的定期任务,或者能够通过附加功能增强现有策略。
用户定义的操作允许通过 JSONB 对象进行自由形式的配置,从而实现无限的灵活性和可重用性。
以下部分提供了一些用户定义操作的示例,您可以指定这些操作并随后将其安排为 TimescaleDB 自动化框架的一部分。
创建适用于所有超表的通用数据保留策略,而不是add_retention_policy
. 通过在过程定义中的 PERFORM 查询中添加 WHERE 子句,可以使用其他过滤器进一步完善该策略。
CREATE OR REPLACE PROCEDURE generic_retention (job_id int, config jsonb)
LANGUAGE PLPGSQL
AS $$
DECLARE
drop_after interval;
BEGIN
SELECT jsonb_object_field_text (config, 'drop_after')::interval INTO STRICT drop_after;
IF drop_after IS NULL THEN
RAISE EXCEPTION 'Config must have drop_after';
END IF;
PERFORM drop_chunks(format('%I.%I', table_schema, table_name), older_than => drop_after)
FROM timescaledb_information.hypertables;
END
$$;
注册作业以在所有超过 12 个月的超表上运行每日删除块。
SELECT add_job('generic_retention','1d', config => '{"drop_after":"12 month"}');
将超过特定时间的块移动到不同表空间的操作。
CREATE OR REPLACE PROCEDURE move_chunks (job_id int, config jsonb)
LANGUAGE PLPGSQL
AS $$
DECLARE
ht REGCLASS;
lag interval;
destination name;
chunk REGCLASS;
tmp_name name;
BEGIN
SELECT jsonb_object_field_text (config, 'hypertable')::regclass INTO STRICT ht;
SELECT jsonb_object_field_text (config, 'lag')::interval INTO STRICT lag;
SELECT jsonb_object_field_text (config, 'tablespace') INTO STRICT destination;
IF ht IS NULL OR lag IS NULL OR destination IS NULL THEN
RAISE EXCEPTION 'Config must have hypertable, lag and destination';
END IF;
FOR chunk IN
SELECT show.oid
FROM show_chunks(ht, older_than => lag)
SHOW (oid)
INNER JOIN pg_class pgc ON pgc.oid = show.oid
INNER JOIN pg_tablespace pgts ON pgts.oid = pgc.reltablespace
WHERE pgts.spcname != destination;
LOOP
RAISE NOTICE 'Moving chunk: %', chunk::text;
EXECUTE format('ALTER TABLE %s SET TABLESPACE %I;', chunk, destination);
END LOOP;
END
$$;
注册作业以将超表指标上超过 12 个月的每日块移动到表空间 old_chunks。
SELECT add_job('move_chunks','1d', config => '{"hypertable":"metrics","lag":"12 month","tablespace":"old_chunks"}');
上述操作使用更简单ALTER TABLE ... SET TABLESPACE
的方法来移动块,但也可以用 TimescaleDB 的 move_chunk
. 该move_chunk
函数还需要一个索引作为输入,但在移动过程中执行数据重新排序(为了更快的后续查询)并且需要较低的锁定级别,因此在移动过程中该块仍可用于读取。
metrics
对超过特定年龄的超表上的块进行下采样和压缩的操作。示例查询计算一个简单avg
的每小时数据以进行下采样,但此查询可以任意复杂。
CREATE OR REPLACE PROCEDURE downsample_compress (job_id int, config jsonb)
LANGUAGE PLPGSQL
AS $$
DECLARE
lag interval;
chunk REGCLASS;
tmp_name name;
BEGIN
SELECT jsonb_object_field_text (config, 'lag')::interval INTO STRICT lag;
IF lag IS NULL THEN
RAISE EXCEPTION 'Config must have lag';
END IF;
FOR chunk IN
SELECT show.oid
FROM show_chunks('metrics', older_than => lag) SHOW (oid)
INNER JOIN pg_class pgc ON pgc.oid = show.oid
INNER JOIN pg_namespace pgns ON pgc.relnamespace = pgns.oid
INNER JOIN timescaledb_information.chunks chunk ON chunk.chunk_name = pgc.relname
AND chunk.chunk_schema = pgns.nspname
WHERE chunk.is_compressed::bool = FALSE
LOOP
RAISE NOTICE 'Processing chunk: %', chunk::text;
-- build name for temp table
SELECT '_tmp' || relname
FROM pg_class
WHERE oid = chunk INTO STRICT tmp_name;
-- copy downsampled chunk data into temp table
EXECUTE format($sql$ CREATE UNLOGGED TABLE %I AS
SELECT time_bucket('1h', time), device_id, avg(value) FROM %s GROUP BY 1, 2;
$sql$, tmp_name, chunk);
-- clear original chunk
EXECUTE format('TRUNCATE %s;', chunk);
-- copy downsampled data back into chunk
EXECUTE format('INSERT INTO %s(time, device_id, value) SELECT * FROM %I;', chunk, tmp_name);
-- drop temp table
EXECUTE format('DROP TABLE %I;', tmp_name);
PERFORM compress_chunk (chunk);
COMMIT;
END LOOP;
END
$$;
注册作业以运行每日下采样和压缩超过 12 个月的块。
SELECT add_job('downsample_compress','1d', config => '{"lag":"12 month"}');
备份还原
备份 TimescaleDB 可以利用 PostgreSQL 已经提供的可靠功能。有几种方法可以做到这一点:使用pg_basebackup
或其他工具进行物理备份,或使用pg_dump
and进行逻辑备份pg_restore
。物理备份也可以与预写日志 (WAL) 归档一起使用,以实现持续备份。
WARNING
TimescaleDB 目前不原生支持多节点环境的一致还原点。应注意确保第三方解决方案在备份之前适当地静默环境,以便跨节点使用的备份点没有未完成的事务。
来源 https://mp.weixin.qq.com/s/GGANfiCGZL5EHcStwWm4MA
相关文章