
Жили были item-ы и было у них sequential numeric id.
То, что оно sequential - это тяжелое наследие царского режима, потом пришли большевики, но ничего сделать было уже нельзя.
#0
И вот, при Николае-батюшке, было это autoincrement поле в MS SQL, item-ы получали id при вставке и никто горя не знал. Очевидно для того, что бы узнать это id на клиенте надо вставлять item-ы один за другим.
#1
Нагрузка возросла - власть поменялась, хостов баз данных стало больше одного, генерацию вынесли в отдельную таблицу. Простой инкремент. Продолжали вставлять один за другим.
#2
Нагрузка возросла - сделали вставку item-ов сразу пачками, а генерацию соответсвенно тоже поменяли, что бы генерировать сразу на всю пачку за один запрос. Стандартная hi-lo процедура (см ниже). Скажем, если вставляется 10 записей - один запрос на генерацию 10 ids.
#3
Нагрузка возросла - сделали пре-генерацию id наперёд блоками и кеширование этого блока на клиенте. Скажем, если вставляется 10 записей - один запрос на генерацию 1000 ids. 10 используются сразу, а 990 ждут следующего раза.
При порядка 700 витках (threads), которые всё время пишут в базу, эффект поразительный.

А вот если бы сесть и подумать, можно было бы сразу с последнего пункта начать…
hi-lo cхема выглядит так:
Таблица в БД
CREATE TABLE IDTable( TableName varchar(255) NOT NULL, NextID bigint NOT NULL, CONSTRAINT IDTable1_PK PRIMARY KEY CLUSTERED( TableName ASC)
SQL запрос на генерацию примерно так
DECLARE @LocalTempTable table(id int) DECLARE @NEXTID INT DECLARE @CNT INT BEGIN TRAN SELECT @NEXTID = (SELECT NextID FROM IDTable WITH (UPDLOCK) WHERE TableName = @@TABLENAME) SET @CNT = 0 WHILE(@CNT < @@COUNT) BEGIN INSERT INTO @LocalTempTable(id) VALUES(@NEXTID + @CNT) SET @CNT = @CNT + 1 END UPDATE IDTable WITH (UPDLOCK) SET NextID = @NEXTID+@CNT WHERE TableName = @@TABLENAME COMMIT SELECT id FROM @LocalTempTable
Где TABLENAME это имя последовательности, а COUNT это размер пачки.
Самый интересный фокус тут это SELECT … WITH (UPDLOCK). Клиенты делают запросы указывая размер пачки, а потом либо тратят ее всё как в случае #2 либо кешируют часть про запас, как в случае #3.
Некоторые размер пачки хранят прямо в таблице, отсюда и название. У этого подхода есть одно достоинство - можно централизованно управлять сколько ID создать. Но это же одновременно и недостаток - часто нужно здесь создать1000 штук, а тут только 10.
Вот тут есть не плохой обзор доступных способов получения ID