पोस्टग्रेज 10 में "डिक्लेरेटिव पार्टिशनिंग" पेश किया गया था, जो आपको काम के एक अच्छे सौदे से छुटकारा दिला सकता है जैसे कि ट्रिगर्स या नियमों को बड़े पैमाने पर उत्पन्न करना/अन्यथा सही टेबल पर रीडायरेक्ट करना। Postgres अब इसे स्वचालित रूप से कर सकता है। आइए माइग्रेशन के साथ शुरू करें:
-
पुरानी तालिका का नाम बदलें और एक नई विभाजित तालिका बनाएं
alter table myTable rename to myTable_old; create table myTable_master( forDate date not null, key2 int not null, value int not null ) partition by range (forDate);
इसके लिए शायद ही किसी स्पष्टीकरण की आवश्यकता हो। पुरानी तालिका का नाम बदल दिया गया है (डेटा माइग्रेशन के बाद हम इसे हटा देंगे) और हमें अपने विभाजन के लिए एक मास्टर टेबल मिलती है जो मूल रूप से हमारी मूल तालिका के समान है, लेकिन बिना अनुक्रमणिका के)
-
एक ऐसा फ़ंक्शन बनाएं जो नए विभाजन उत्पन्न कर सके जैसा हमें उनकी आवश्यकता है:
create function createPartitionIfNotExists(forDate date) returns void as $body$ declare monthStart date := date_trunc('month', forDate); declare monthEndExclusive date := monthStart + interval '1 month'; -- We infer the name of the table from the date that it should contain -- E.g. a date in June 2005 should be int the table mytable_200506: declare tableName text := 'mytable_' || to_char(forDate, 'YYYYmm'); begin -- Check if the table we need for the supplied date exists. -- If it does not exist...: if to_regclass(tableName) is null then -- Generate a new table that acts as a partition for mytable: execute format('create table %I partition of myTable_master for values from (%L) to (%L)', tableName, monthStart, monthEndExclusive); -- Unfortunatelly Postgres forces us to define index for each table individually: execute format('create unique index on %I (forDate, key2)', tableName); end if; end; $body$ language plpgsql;
यह बाद में काम आएगा।
-
एक ऐसा दृश्य बनाएं जो मूल रूप से केवल हमारे मास्टर टेबल को दर्शाता है:
create or replace view myTable as select * from myTable_master;
-
नियम बनाएं ताकि जब हम नियम में सम्मिलित हों, तो हम न केवल विभाजित तालिका को अपडेट करेंगे, बल्कि यदि आवश्यक हो तो एक नया विभाजन भी बनाएंगे:
create or replace rule autoCall_createPartitionIfNotExists as on insert to myTable do instead ( select createPartitionIfNotExists(NEW.forDate); insert into myTable_master (forDate, key2, value) values (NEW.forDate, NEW.key2, NEW.value) );
बेशक, अगर आपको update
की भी आवश्यकता है और delete
, आपको उन लोगों के लिए भी एक नियम की आवश्यकता है जो सीधे आगे होने चाहिए।
-
वास्तव में पुरानी तालिका को माइग्रेट करें:
-- Finally copy the data to our new partitioned table insert into myTable (forDate, key2, value) select * from myTable_old; -- And get rid of the old table drop table myTable_old;
अब टेबल का माइग्रेशन पूरा हो गया है, इसके बिना यह जानने की जरूरत है कि कितने पार्टिशन की जरूरत है और यह भी देखें कि myTable
बिल्कुल पारदर्शी होगा। आप पहले की तरह उस तालिका से सरल सम्मिलित और चयन कर सकते हैं, लेकिन आपको विभाजन से प्रदर्शन लाभ मिल सकता है।
ध्यान दें कि दृश्य केवल आवश्यक है, क्योंकि विभाजित तालिका में पंक्ति ट्रिगर नहीं हो सकते हैं। यदि आप createPartitionIfNotExists
calling को कॉल करने के साथ मिल सकते हैं मैन्युअल रूप से जब भी आपके कोड से आवश्यकता हो, आपको दृश्य और उसके सभी नियमों की आवश्यकता नहीं है। इस मामले में आपको माइग्रेशन के दौरान मैन्युअल रूप से विभाजन जोड़ने की आवश्यकता होती है:
do
$$
declare rec record;
begin
-- Loop through all months that exist so far...
for rec in select distinct date_trunc('month', forDate)::date yearmonth from myTable_old loop
-- ... and create a partition for them
perform createPartitionIfNotExists(rec.yearmonth);
end loop;
end
$$;