本节包含一些关于持续聚合常见问题故障排除的想法。
持续聚合使用水印来指示哪些时间桶已经被物化。当您查询持续聚合时,您的查询会返回水印之前物化的数据。它返回水印之后的实时、非物化数据。
在某些情况下,水印可能位于未来。如果发生这种情况,所有桶,包括最近的桶,都将被物化并低于水印。不会返回实时数据。
如果您在 <START_TIME>, NULL
时间窗口内刷新您的持续聚合,这可能会发生,这将物化所有最近的数据。如果您使用 WITH DATA
选项创建持续聚合,也可能发生这种情况。这也隐式地使用 NULL, NULL
窗口刷新您的持续聚合。
要解决此问题,请使用 WITH NO DATA
选项创建一个新的持续聚合。然后使用策略在显式时间窗口内刷新此持续聚合。
使用
WITH NO DATA
选项创建持续聚合CREATE MATERIALIZED VIEW <continuous_aggregate_name>WITH (timescaledb.continuous)AS SELECT time_bucket('<interval>', <time_column>),<other_columns_to_select>,...FROM <hypertable>GROUP BY bucket, <optional_other_columns>WITH NO DATA;使用具有显式
end_offset
的策略刷新持续聚合。例如SELECT add_continuous_aggregate_policy('<continuous_aggregate_name>',start_offset => INTERVAL '30 day',end_offset => INTERVAL '1 hour',schedule_interval => INTERVAL '1 hour');检查新的持续聚合的水印,确保它位于过去,而不是未来。
获取包含实际持续聚合数据的物化超表的 ID
SELECT id FROM _timescaledb_catalog.hypertableWHERE table_name=(SELECT materialization_hypertable_nameFROM timescaledb_information.continuous_aggregatesWHERE view_name='<continuous_aggregate_name>');使用返回的 ID 查询水印的时间戳
对于 TimescaleDB >= 2.12
SELECT COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(<ID>)),'-infinity'::timestamp with time zone);对于 TimescaleDB < 2.12
SELECT COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(<ID>)),'-infinity'::timestamp with time zone);
警告
如果您选择在创建新的持续聚合后删除旧的持续聚合,请注意历史数据丢失。如果您的旧持续聚合包含您从原始超表中删除的数据(例如通过数据保留策略删除),则删除的数据不会包含在新的持续聚合中。
ERROR: cannot create continuous aggregate with incompatible bucket widthDETAIL: Time bucket width of "<BUCKET>" [1 year] should be multiple of the time bucket width of "<BUCKET>" [1 day].
如果您尝试创建分层持续聚合,则必须使用兼容的时间桶。您不能在具有可变宽度时间桶的持续聚合之上创建具有固定宽度时间桶的持续聚合。有关更多信息,请参阅分层持续聚合中的限制部分。
在超表上设置的保留策略不适用于从超表创建的任何持续聚合。这允许您为原始数据和汇总数据设置不同的保留期限。要将保留策略应用于持续聚合,请在持续聚合本身上设置策略。
物化视图通常与有序数据一起使用。如果您插入历史数据或与当前时间无关的数据,则需要刷新策略并重新评估从过去到现在拖动的值。
您可以为超表设置插入后规则或 upsert,以触发可以验证数据合并时需要刷新的内容。
假设您插入了名为 A、B、D 和 F 的有序时间范围,并且您已经有一个持续聚合正在查找此数据。如果您现在插入 E,则需要刷新 E 和 F。但是,如果您插入 C,我们将需要刷新 C、D、E 和 F。
例如
- A、B、D 和 F 已经在一个视图中物化,其中包含所有数据。
- 要插入 C,请将数据拆分为
AB
和DEF
子集。 AB
是一致的,物化数据也是如此;您只需要重用它。- 插入 C、
DEF
,并在 C 之后刷新策略。
这可能会占用大量资源来处理,特别是如果您的过去有任何重要数据也需要带到现在。
考虑一个示例,您在单个超表上有 300 列,并在持续聚合中使用其中的五列。在这种情况下,刷新可能很困难,将这些列隔离到另一个超表中可能更有意义。或者,您可以为每个指标创建一个超表并独立刷新它们。
使用 cagg_migrate
将持续聚合从旧格式迁移到新格式时,可能会遇到权限错误。执行迁移的用户必须具有以下权限
- 对表
_timescale_catalog.continuous_agg_migrate_plan
和_timescale_catalog.continuous_agg_migrate_plan_step
的 Select、insert 和 update 权限 - 对序列
_timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq
的 Usage 权限
要解决此问题,请切换到有权授予权限的用户,并将以下权限授予执行迁移的用户
GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan TO <USER>;GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan_step TO <USER>;GRANT USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq TO <USER>;
持续聚合并非适用于所有查询。例如,TimescaleDB 不支持持续聚合上的窗口函数。如果您使用不支持的函数,您会看到以下错误
ERROR: invalid continuous aggregate viewSQL state: 0A000
下表总结了持续聚合中支持的聚合函数
函数、子句或特性 | TimescaleDB 2.6 及更早版本 | TimescaleDB 2.7、2.8 和 2.9 | TimescaleDB 2.10 及更高版本 |
---|---|---|---|
可并行化的聚合函数 | ✅ | ✅ | ✅ |
不可并行化的 SQL 聚合 | ❌ | ✅ | ✅ |
ORDER BY | ❌ | ✅ | ✅ |
有序集聚合 | ❌ | ✅ | ✅ |
假设集聚合 | ❌ | ✅ | ✅ |
聚合函数中的 DISTINCT | ❌ | ✅ | ✅ |
聚合函数中的 FILTER | ❌ | ✅ | ✅ |
FROM 子句支持 JOINS | ❌ | ❌ | ✅ |
DISTINCT 在聚合函数中有效,但在查询定义中无效。例如,对于表
CREATE TABLE public.candle(symbol_id uuid NOT NULL,symbol text NOT NULL,"time" timestamp with time zone NOT NULL,open double precision NOT NULL,high double precision NOT NULL,low double precision NOT NULL,close double precision NOT NULL,volume double precision NOT NULL);
- 以下代码有效CREATE MATERIALIZED VIEW candles_start_endWITH (timescaledb.continuous) ASSELECT time_bucket('1 hour', "time"), COUNT(DISTINCT symbol), first(time, time) as first_candle, last(time, time) as last_candleFROM candleGROUP BY 1;
- 以下代码无效CREATE MATERIALIZED VIEW candles_start_endWITH (timescaledb.continuous) ASSELECT DISTINCT ON (symbol)symbol,symbol_id, first(time, time) as first_candle, last(time, time) as last_candleFROM candleGROUP BY symbol_id;
当您查询持续聚合时,实时聚合会自动添加最新的数据。换句话说,它们包括比您上次物化桶更新的数据。
如果您向已物化的桶添加新的历史数据,它不会反映在实时聚合中。您应该等待下一次计划刷新,或通过调用 refresh_continuous_aggregate
手动刷新。您可以将实时聚合视为最终与历史数据一致。
以下示例展示了它的工作原理。
创建并填充超表
CREATE TABLE conditions(day DATE NOT NULL,city text NOT NULL,temperature INT NOT NULL);SELECT create_hypertable('conditions', by_range('day', INTERVAL '1 day'));INSERT INTO conditions (day, city, temperature) VALUES('2021-06-14', 'Moscow', 26),('2021-06-15', 'Moscow', 22),('2021-06-16', 'Moscow', 24),('2021-06-17', 'Moscow', 24),('2021-06-18', 'Moscow', 27),('2021-06-19', 'Moscow', 28),('2021-06-20', 'Moscow', 30),('2021-06-21', 'Moscow', 31),('2021-06-22', 'Moscow', 34),('2021-06-23', 'Moscow', 34),('2021-06-24', 'Moscow', 34),('2021-06-25', 'Moscow', 32),('2021-06-26', 'Moscow', 32),('2021-06-27', 'Moscow', 31);
创建一个持续聚合,但不物化任何数据。请注意,默认情况下启用实时聚合
CREATE MATERIALIZED VIEW conditions_summaryWITH (timescaledb.continuous) ASSELECT city,time_bucket('7 days', day) AS bucket,MIN(temperature),MAX(temperature)FROM conditionsGROUP BY city, bucketWITH NO DATA;The select query returns data as real time aggregates are enabled. The query onthe continuous aggregate fetches data directly from the hypertable:SELECT * FROM conditions_summary ORDER BY bucket;city | bucket | min | max--------+------------+-----+-----Moscow | 2021-06-14 | 22 | 30Moscow | 2021-06-21 | 31 | 34
将数据物化到持续聚合中
CALL refresh_continuous_aggregate('conditions_summary', '2021-06-14', '2021-06-21');The select query returns the same data, as expected, but this time the data isfetched from the underlying materialized tableSELECT * FROM conditions_summary ORDER BY bucket;city | bucket | min | max--------+------------+-----+-----Moscow | 2021-06-14 | 22 | 30Moscow | 2021-06-21 | 31 | 34
更新先前物化桶中的数据
UPDATE conditionsSET temperature = 35WHERE day = '2021-06-14' and city = 'Moscow';
当您查询持续聚合时,更新后的数据尚不可见。这是因为这些更改尚未物化。(同样,任何 INSERT 或 DELETE 也将不可见)。
SELECT * FROM conditions_summary ORDER BY bucket;city | bucket | min | max--------+------------+-----+-----Moscow | 2021-06-14 | 22 | 30Moscow | 2021-06-21 | 31 | 34
再次刷新数据以更新先前物化的区域
CALL refresh_continuous_aggregate('conditions_summary', '2021-06-14', '2021-06-21');SELECT * FROM conditions_summary ORDER BY bucket;city | bucket | min | max--------+------------+-----+-----Moscow | 2021-06-14 | 22 | 35Moscow | 2021-06-21 | 31 | 34
当您有一个使用上次观测值向前结转 (locf) 函数的查询时,该查询默认情况下会向前结转 NULL 值。如果您希望该函数忽略 NULL 值,则可以将 treat_null_as_missing=TRUE
设置为查询中的第二个参数。例如
dev=# select * FROM (select time_bucket_gapfill(4, time,-5,13), locf(avg(v)::int,treat_null_as_missing:=true) FROM (VALUES (0,0),(8,NULL)) v(time, v) WHERE time BETWEEN 0 AND 10 GROUP BY 1) i ORDER BY 1 DESC;time_bucket_gapfill | locf---------------------+------12 | 08 | 04 | 00 | 0-4 |-8 |(6 rows)
您的计划作业可能会因各种原因停止运行。在自托管 TimescaleDB 上,您可以通过重启后台工作进程来解决此问题
在 Timescale 和 Managed Service for TimescaleDB 上,通过执行以下操作之一来重启后台工作进程
- 运行
SELECT timescaledb_pre_restore()
,然后运行SELECT timescaledb_post_restore()
。 - 关闭服务电源然后再打开。这可能会导致服务从备份还原并重放预写日志时停机几分钟。
关键词
在此页面上发现问题?报告问题 或 在 GitHub 上编辑此页面。