0

我想加快以下(PostgreSQL)代码的速度,我推测它会有助于摆脱(一些)循环,但我看不到这样做的方法。欢迎任何关于加速的建议。提前致谢!

该代码为不同部分的每列计算一些统计数据(平均值、斜率)。该部分由滑动时间窗口(例如 60 分钟)确定。所以下面的代码

  • 循环遍历我对计算其统计数据感兴趣的不同列
  • 对于每一列,我依次移动我的时间窗口并计算该窗口中值的统计信息。

    for col_name in ..... a list of column names
    truncate small_table;           -- where statistics are temporarily stored
    for cur in select time from big_table loop
        execute 'select regr_slope('|| col_name ||', time) as slope,'
            || ' avg(' || col_name || ') as mean'
            || ' from big_table where'
            || ' time <=' || cur.time
            || ' and time >=' || cur.time-60
            into result;
    
        execute 'insert into small_table values($1,$2,$3)'
            using cur.time, result.slope, result.mean;
    end loop;
    
    execute 'update big_table set '
        || col_name || '_slope = small_table.slope, '
        || col_name || '_mean = small_table.mean '
        || ' where big_table.time=small_table.time';
    end loop;
    

small_table,结果被临时存储,被引入以避免多次更新big_table.

small_tablebig_table具有相同的结构,但小表的行数要少得多。两个表的列是
time | field_1 | field_2 | field_1_slope | field_1_mean | field_2_slope | field_2_mean

实际上有很多列(〜50),这可能是另一个放缓的因素?

4

1 回答 1

0

如果您动态生成以下 SQL 模式,您至少可以在一个查询中执行所有这些操作。不过,我不确定它是否会表现得更好(显然你需要遍历所有列并将它们添加进去)。在我担心在代码中构建 SQL 之前,我会测试性能。

Update
    big_table b
Set
    field1_slope = x.field1_slope,
    field1_mean = x.field1_mean,
    field2_slope = x.field2_slope,
    field2_mean = x.field2_mean
From (
    Select
        b1.time,
        regr_slope(b2.field1, b2.time) field1_slope,
        avg(b2.field1) field1_mean,
        regr_slope(b2.field2, b2.time) field2_slope,
        avg(b2.field2) field2_mean
    From
        big_table b1
            Inner Join
        big_table b2
            On b2.time >= b1.time and b2.time < b1.time + 60
    Group By
        b1.time
    ) x
Where
    b.time = x.time;

我对 PostgreSQL 不太熟悉,可能有一种方法可以消除对大表的引用之一。

示例 SQL 小提琴

另一种使用游标的方法

于 2013-08-30T22:22:16.013 回答