2017-07-07 42 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

相關問題