सारांश मान को बनाए रखना मुश्किल है - डेडलॉक की संभावना बनाना आसान है आपका कार्यक्रम।
यदि आपको वास्तव में ऐसा करना है, क्योंकि आप जानते हैं कि आपको प्रदर्शन की समस्याएँ होंगी अन्यथा (जैसे सैकड़ों या अधिक में nhunts), तो बेहतर होगा कि nhunts के लिए एक अलग सारांश तालिका बनाई जाए, कुछ इस तरह:
CREATE TABLE hunts_summary
(
id_hs bigserial primary key,
id_h integer NOT NULL,
nhunts integer NOT NULL
);
CREATE INDEX hunts_summary_id_h_idx on hunts_summary(id_h);
शिकार के लिए ट्रिगर:
- प्रत्येक जोड़ी गई, हटाई गई, अपडेट की गई पंक्ति के लिए चलती है;
- एक पंक्ति जोड़ता है
(id_h, nhunts) = (NEW.id_h, 1)
प्रत्येक डालने पर; - एक पंक्ति जोड़ता है
(id_h, nhunts) = (OLD.id_h, -1)
प्रत्येक डिलीट पर; - उपरोक्त दोनों अपडेट पर जो
id_h
को बदलता है ।
चूंकि ट्रिगर केवल नई पंक्तियों को जोड़ देगा, यह मौजूदा पंक्तियों को लॉक नहीं करता है और इसलिए यह गतिरोध नहीं कर सकता है।
लेकिन यह पर्याप्त नहीं है - जैसा कि ऊपर वर्णित सारांश तालिका शिकार तालिका की तुलना में पंक्तियों को तेज़ी से या तेज़ी से बढ़ेगी, इसलिए यह बहुत उपयोगी नहीं है। इसलिए हमें मौजूदा पंक्तियों को समय-समय पर मर्ज करने के लिए कुछ तरीके जोड़ने की जरूरत है - किसी तरह बदलने के लिए:
id_h nhunts
1 1
1 1
2 1
2 -1
1 1
1 -1
2 1
1 1
2 1
प्रति:
id_h nhunts
1 3
2 2
यह प्रत्येक ट्रिगर आमंत्रण पर नहीं चलना चाहिए, क्योंकि यह तब काफी धीमा होगा, लेकिन यह यादृच्छिक रूप से चल सकता है - उदाहरण के लिए यादृच्छिक रूप से प्रत्येक 1/1024 वें आमंत्रण। अन्यथा संभावित गतिरोध से बचने के लिए, यह फ़ंक्शन पहले से लॉक की गई पंक्तियों को छूने से बचने के लिए "स्किप लॉक" कीवर्ड का उपयोग करेगा।
ऐसा ट्रिगर कुछ इस तरह दिखेगा:
create or replace function hunts_maintain() returns trigger
as $hunts_maintain$
begin
if (tg_op = 'INSERT') then
insert into hunts_summary(id_h, nhunts)
values (NEW.id_h, 1);
elsif (tg_op = 'DELETE') then
insert into hunts_summary(id_h, nhunts)
values (OLD.id_h, -1);
elsif (tg_op = 'UPDATE' and NEW.id_h!=OLD.id_h) then
insert into hunts_summary(id_h, nhunts)
values (OLD.id_h, -1), (NEW.id_h, 1);
end if;
if (random()*1024 < 1) then
with deleted_ids as (
select id_hs from hunts_summary for update skip locked
),
deleted_nhunts as (
delete from hunts_summary where id_hs in (select id_hs from deleted_ids) returning id_h, nhunts
)
insert into hunts_summary (id_h, nhunts) select id_h, sum(nhunts) from deleted_nhunts group by id_h;
end if;
return NEW;
end;
$hunts_maintain$ language plpgsql;
create trigger hunts_maintain
after insert or update or delete on hunts
for each row execute procedure hunts_maintain();
मेरे लैपटॉप पर ट्रिगर इतनी तेजी से चलता है कि 45 के दशक में तालिका में 1M पंक्तियों को सम्मिलित करता है।
नीचे दिया गया यह दृश्य सारांश से वर्तमान ननहंट को निकालना आसान बना देगा। इसे क्वेरी करने में एक छोटी संख्या या एमएस लगेगा, भले ही हंट्स टेबल अरबों में हो:
create or replace view hunts_summary_view as
select id_h, sum(nhunts) as nhunts
from hunts_summary
group by id_h;