2017-07-07 43 views
0

我每小时和每天都有2个表格,我的目标是计算小时表格中的平均值并将其保存到日常表格中。我写了这样的触发功能 -postgres触发器功能只在另一个表格中插入少量记录

CREATE OR REPLACE FUNCTION public.calculate_daily_avg() 
RETURNS trigger AS 
$BODY$ 
DECLARE chrly CURSOR for 
SELECT device, date(datum) datum, avg(cpu_util) cpu_util 
FROM chourly WHERE date(datum) = current_date group by device, date(datum); 

BEGIN 

    FOR chrly_rec IN chrly 
    LOOP 

    insert into cdaily (device, datum, cpu_util) 
    values (chrly_rec.device, chrly_rec.datum, chrly_rec.cpu_util) 
     on conflict (device, datum) do update set 
     device=chrly_rec.device, datum=chrly_rec.datum, cpu_util=chrly_rec.cpu_util; 

    return NEW; 

    END LOOP; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
     RAISE NOTICE 'NO DATA IN chourly FOR %', current_date; 

END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
ALTER FUNCTION public.calculate_daily_avg() 
    OWNER TO postgres; 

像这样每小时的表的触发器 -

CREATE TRIGGER calculate_daily_avg_trg 
    BEFORE INSERT OR UPDATE 
    ON public.chourly 
    FOR EACH ROW 
    EXECUTE PROCEDURE public.calculate_daily_avg(); 

但是当我尝试在每小时表中插入或更新约3000只记录3 4设备插入,而不是3000.(也在触发器中,我已经试过AFTER INSERT或UPDATE,但即使这样也给出相同的结果)我在这里做错了什么?如果您觉得我写错了,请提出任何更好的写触发器的方法。谢谢!

回答

0

INSERT时,我不建议使用TRIGGER进行计算。使用按cron每小时或每日执行的函数尝试不同的方法。

为什么?

因为每次你INSERT一行。 postgres将始终为插入(根据您的流量)执行聚合函数AVG()LOOPING

这意味着又INSERT语句将等到Previous INSERT COMMITED将遭受高度INSERT Transaction你的数据库的性能。如果你以某种方式管理BREAK规则(可能来自配置),你会得到inconsistent数据,比如你现在发生的事情。

+1

感谢您对Adrian的解释。如果我需要坚持触发,那么不能以某种方式通过添加睡眠来等待触发器中的所有插入?尽管如此,Cron方法似乎是更好的选择。 – dappler

+0

@dappler不,你不能通过添加睡眠,因为你不知道确切的查询执行时间。如果你以某种方式放置睡眠(比方说20秒),当高流量是好的。但是当低流量插入也等待20秒。我们不希望发生这种情况。 cron方法要比牺牲交易性能和潜在的僵局更好。 –

+0

你说得好点阿德里安。我用函数替换了触发函数,并从java中调用它。谢谢! – dappler

相关问题