Основная проблема с этим - особенно с требованием уникальности - на уровне постоянства заключается в том, что вы не можете гарантировать, что ваше приложение является единственным приложением, попавшим в базу данных.На самом деле, держу пари, что сейчас есть еще как минимум два приложения, которые пройдут прямо за Java - графический интерфейс вашего dbms и интерфейс командной строки вашего dbms.(В последнем контракте с полным рабочим днем, который я заключил, заявки, написанные на более чем двух десятках языков в течение 30 лет, попали в основную производственную базу данных.)
Грубая сила всегда работает.(Но может создать горячую точку.)
Вы можете сгенерировать свои внутренние идентификаторы сегодня и сохранить их в таблице.
create table internal_iden (
iden char(17) primary key
check (iden ~ '2[0-9]{3}-FLD-[0-9]{8}'),
taken_by varchar(15) null,
taken_at timestamp null
);
Ограничение CHECK () гарантирует, что вставленные значения соответствуют регулярному выражению.(PostgreSQL поддерживает регулярные выражения POSIX среди прочих; оператор "~" сообщает dbms, что это сравнение ожидает регулярного выражения POSIX.) В зависимости от требований вашего приложения, вы можете или не хотите, чтобы другие таблицы устанавливали ссылку на внешний ключ для этой таблицы internal_iden.
insert into internal_iden (iden) values
('2012-FLD-00000001'),
('2012-FLD-00000002'),
('2012-FLD-00000003'),
('2012-FLD-00000004'),
('2012-FLD-00000005'),
('2012-FLD-00000006'),
('2012-FLD-00000007'),
('2012-FLD-00000008'),
('2012-FLD-00000000'),
('2012-FLD-00000010'),
('2012-FLD-00000011'),
('2012-FLD-00000012');
Затем вы можете создать хранимую процедуру или функцию, чтобы обернуть эти два оператора в одну транзакцию.
select min(iden)
from internal_iden
where taken_by is null;
update internal_iden
set taken_by = 'server1',
taken_at = current_timestamp
where iden = (select min(iden)
from internal_iden
where taken_by is null);
На самом деле, в хранимой процедуре вы можете заменить этоподзапрос в последнем предложении WHERE с буквальным значением идентификатора, который вы получили из инструкции SELECT.Частичный индекс take_by может повысить производительность.(Если ваша база данных поддерживает частичные индексы.)
create index ix1 on internal_iden (taken_by)
where (taken_by is null);
Максимальное количество строк в год составляет около 100 миллионов.Существует несколько способов обработки такого количества строк.
- Создайте их все сразу и живите с ними.
- Создайте их все сразу и разделите таблицу.
- Создайте миллион и запустите задание cron, которое подсчитывает количество свободных идентификаторов и добавляет еще миллион, когда число уменьшается.
- Пусть хранимая процедура позаботится о добавлении идентификаторов по мере необходимости.
Имейте в виду разделение, если продолжите эту идею.