Postgresql postgres触发器函数仅在另一个表中插入少量记录

Postgresql postgres触发器函数仅在另一个表中插入少量记录,postgresql,triggers,Postgresql,Triggers,我每小时和每天有两个表,我的目标是计算每小时表的平均值,并将其保存到每日表。我已经写了一个这样的触发器函数- 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)

我每小时和每天有两个表,我的目标是计算每小时表的平均值,并将其保存到每日表。我已经写了一个这样的触发器函数-

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条。(同样在触发器中,我在插入或更新后已经尝试过,但即使这样也会得到相同的结果)我在这里做错了什么?如果你觉得我写错了,请提出更好的方法来写触发器。谢谢

我不建议在
插入时使用
触发器
进行计算。尝试不同的方法,使用cron每小时或每天执行的函数

为什么?

因为每次你插入一行。postgres将始终执行插入的聚合函数
AVG()
循环
(基于您的流)


这意味着另一个
INSERT
语句将等待
上一次INSERT
提交,这将影响数据库在高度
INSERT事务中的性能。如果您设法
打破规则(可能来自配置),您将得到
不一致的
数据,比如您现在发生的事情。

我不建议在
插入时使用
触发器
进行计算。尝试不同的方法,使用cron每小时或每天执行的函数

为什么?

因为每次你插入一行。postgres将始终执行插入的聚合函数
AVG()
循环
(基于您的流)


这意味着另一个
INSERT
语句将等待
上一次INSERT
提交,这将影响数据库在高度
INSERT事务中的性能。如果你设法打破了规则(可能来自配置),你会得到不一致的数据,比如你现在发生的事情。

谢谢你解释得很好Adrian。如果我需要坚持使用触发器,那么我是否可以通过添加睡眠来等待触发器中的所有插入?尽管如此,Cron方法似乎是更好的选择。@dappler不,您不能通过添加睡眠,因为您不知道确切的查询执行时间。如果你在高流量的情况下睡眠(比如说20秒)。但当低流量时,插入也会等待20秒。我们不希望这种情况发生。cron方法比牺牲事务性能和潜在死锁要好得多。我将触发器函数替换为just函数,并从java调用它。谢谢谢谢你的解释,阿德里安。如果我需要坚持使用触发器,那么我是否可以通过添加睡眠来等待触发器中的所有插入?尽管如此,Cron方法似乎是更好的选择。@dappler不,您不能通过添加睡眠,因为您不知道确切的查询执行时间。如果你在高流量的情况下睡眠(比如说20秒)。但当低流量时,插入也会等待20秒。我们不希望这种情况发生。cron方法比牺牲事务性能和潜在死锁要好得多。我将触发器函数替换为just函数,并从java调用它。谢谢