यह अच्छा होगा यदि PostgreSQL MySQL के MyISAM तालिकाओं की तरह "एक बहु-स्तंभ अनुक्रमणिका में द्वितीयक स्तंभ पर" वृद्धि का समर्थन करता है
हाँ, लेकिन ध्यान दें कि ऐसा करने पर, MyISAM आपकी पूरी टेबल को लॉक कर देता है। जो तब समवर्ती लेन-देन की चिंता किए बिना सबसे बड़ा +1 ढूंढना सुरक्षित बनाता है।
Postgres में, आप यह भी कर सकते हैं, और पूरी तालिका को लॉक किए बिना। एक एडवाइजरी लॉक और एक ट्रिगर काफी अच्छा होगा:
CREATE TYPE animal_grp AS ENUM ('fish','mammal','bird');
CREATE TABLE animals (
grp animal_grp NOT NULL,
id INT NOT NULL DEFAULT 0,
name varchar NOT NULL,
PRIMARY KEY (grp,id)
);
CREATE OR REPLACE FUNCTION animals_id_auto()
RETURNS trigger AS $$
DECLARE
_rel_id constant int := 'animals'::regclass::int;
_grp_id int;
BEGIN
_grp_id = array_length(enum_range(NULL, NEW.grp), 1);
-- Obtain an advisory lock on this table/group.
PERFORM pg_advisory_lock(_rel_id, _grp_id);
SELECT COALESCE(MAX(id) + 1, 1)
INTO NEW.id
FROM animals
WHERE grp = NEW.grp;
RETURN NEW;
END;
$$ LANGUAGE plpgsql STRICT;
CREATE TRIGGER animals_id_auto
BEFORE INSERT ON animals
FOR EACH ROW WHEN (NEW.id = 0)
EXECUTE PROCEDURE animals_id_auto();
CREATE OR REPLACE FUNCTION animals_id_auto_unlock()
RETURNS trigger AS $$
DECLARE
_rel_id constant int := 'animals'::regclass::int;
_grp_id int;
BEGIN
_grp_id = array_length(enum_range(NULL, NEW.grp), 1);
-- Release the lock.
PERFORM pg_advisory_unlock(_rel_id, _grp_id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql STRICT;
CREATE TRIGGER animals_id_auto_unlock
AFTER INSERT ON animals
FOR EACH ROW
EXECUTE PROCEDURE animals_id_auto_unlock();
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
यह पैदावार:
grp | id | name
--------+----+---------
fish | 1 | lax
mammal | 1 | dog
mammal | 2 | cat
mammal | 3 | whale
bird | 1 | penguin
bird | 2 | ostrich
(6 rows)
एक चेतावनी है। एडवाइजरी लॉक जारी होने तक या सत्र समाप्त होने तक आयोजित किए जाते हैं। यदि लेन-देन के दौरान कोई त्रुटि होती है, तो ताला चारों ओर रखा जाता है और आपको इसे मैन्युअल रूप से जारी करने की आवश्यकता होती है।
SELECT pg_advisory_unlock('animals'::regclass::int, i)
FROM generate_series(1, array_length(enum_range(NULL::animal_grp),1)) i;
पोस्टग्रेज 9.1 में, आप अनलॉक ट्रिगर को त्याग सकते हैं, और pg_advisory_lock() कॉल को pg_advisory_xact_lock() से बदल सकते हैं। वह स्वचालित रूप से तब तक आयोजित किया जाता है और लेन-देन के अंत में जारी किया जाता है।
एक अलग नोट पर, मैं एक अच्छे पुराने अनुक्रम का उपयोग करना चाहता हूं। इससे चीज़ें तेज़ हो जाएंगी -- भले ही आप डेटा को देखने पर उतनी सुंदर न दिखें.
अंत में, एक अतिरिक्त तालिका जोड़कर प्रति (वर्ष, माह) कॉम्बो भी एक अद्वितीय अनुक्रम प्राप्त किया जा सकता है, जिसकी प्राथमिक कुंजी एक धारावाहिक है, और जिसका (वर्ष, माह) मान उस पर एक अद्वितीय बाधा है।