【问题标题】:Is it possible to calculate a cumulative sum or moving average with a TimescaleDB continuous aggregate?是否可以使用 TimescaleDB 连续聚合计算累积和或移动平均值?
【发布时间】:2023-04-04 09:42:01
【问题描述】:

考虑一个有 2 列的表格:

create table foo
(
    ts             timestamp,
    precipitation  numeric,
    primary key (ts)
);

使用以下数据:

ts precipitation
2021-06-01 12:00:00 1
2021-06-01 13:00:00 0
2021-06-01 14:00:00 2
2021-06-01 15:00:00 3

我想使用TimescaleDB continuous aggregate 来计算每小时计算一次的此数据的三小时累积总和。使用上面的示例数据,我的连续聚合将包含

ts cum_precipitation
2021-06-01 12:00:00 1
2021-06-01 13:00:00 1
2021-06-01 14:00:00 3
2021-06-01 15:00:00 5

我看不到使用支持的连续聚合语法来执行此操作的方法。我错过了什么吗?本质上,我希望时间段是前面的 x 小时,但计算每小时发生一次。

【问题讨论】:

    标签: sql postgresql timescaledb


    【解决方案1】:

    好问题!

    您可以通过计算一个正常的连续聚合然后对其执行window function 来做到这一点。因此,计算每小时的sum(),然后执行sum(),因为窗口函数会起作用。

    当您遇到更复杂的聚合(如平均值或标准差或百分位近似值等)时,我建议您切换到我们在 TimescaleDB 工具包中引入的一些two-step aggregates。具体来说,我会研究我们最近介绍的statistical aggregates。他们也可以做这种累积和类型的事情。 (它们只适用于 DOUBLE PRECISION 或可以转换为的东西 - 即 FLOAT,我强烈建议你不要使用 NUMERIC 而是切换到双精度或浮点数,看起来不像你真的此处需要无限精度计算)。

    您可以查看我在this presentation 中写的一些查询,但它可能看起来像:

    CREATE MATERIALIZED VIEW response_times_five_min
    WITH (timescaledb.continuous)
    AS SELECT api_id,
        time_bucket('1 hour'::interval, ts) as bucket,
        stats_agg(response_time)
    FROM response_times
    GROUP BY 1, 2;
    
    SELECT bucket, 
        average(rolling(stats_agg) OVER last3), 
        sum(rolling(stats_agg) OVER last3)
    FROM response_times_five_min
    WHERE api_id = 32
    WINDOW last3 as 
    (ORDER BY bucket RANGE '3 hours' PRECEDING);
    

    【讨论】:

    • 谢谢,这个例子很有帮助,演示文稿也很有帮助。小错误last30 -> last3。澄清一下,目前没有办法用连续聚合实际实现滚动平均值或总和,对吗?似乎随着窗口变大,性能提升会变得更加明显。
    • 谢谢!修正错字!
    • 是的,没有办法在连续聚合中进行滚动聚合,因为这会严重影响失效。
    猜你喜欢
    • 2012-06-19
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 2021-11-21
    • 2020-05-18
    相关资源
    最近更新 更多