Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
Да форум читал, все внешние ссылки поломаны, но у меня ограниченные требования, прошу совета по оптимизации.

На таблице есть identity, но использовать напрямую его нельзя в силу некоторых обстоятельств.

create table test2
(
  id int not null identity(1,1) primary key,
  fld int not null ,
  value float
)
go
Create FUNCTION getidtest2()
RETURNS int
AS
BEGIN
  RETURN (SELECT -ISNULL(1+MAX(id),0) FROM test2)
END
go
alter table  test2 add constraint df_test2 DEFAULT ( dbo.getidtest2() ) for fld
go
create trigger tr_test2 on test2
after insert 
as
  update test2 set fld = (select top 1 isnull(1_max(fld),0) from test2 ) where id = (select top 1 id from inserted)
GO

ALTER TABLE test2 ADD  CONSTRAINT idx_test2 UNIQUE NONCLUSTERED (fld ASC)


вставлял в 3 потоках по 10000 батчей с единичными инсертами - все хорошо работает, но может что-то не учел?

insert into test2 (value) values (1)
2 окт 14, 19:43    [16652534]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Версия сервера?
Что за функция 1_max?
2 окт 14, 20:38    [16652743]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Можете вообще сделать fld вычисляемым столбцом:
fld as id
2 окт 14, 20:56    [16652833]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
invm,

pardon isnull(1 + max(fld),0)

MSSQL 2008R2SP3
2 окт 14, 21:37    [16652959]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
invm
Можете вообще сделать fld вычисляемым столбцом:
fld as id


я вроде написал что не могу пользоватся напрямую значениями оттуда
2 окт 14, 21:39    [16652964]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Lepsik
я вроде написал что не могу пользоватся напрямую значениями оттуда
Ок. Был невнимателен.

Все самописные генераторы обязаны иметь для корректной работы точку сериализации. В вашем варианте ее нет. Поэтому будут попытки вставки дубликата ключа. Воспроизводится очень просто:

1. Вспомогательный объект
create table dbo.trigger_table (id int);

2. Открываем в студии новый сеанс и выполняем
begin tran;
select * from dbo.trigger_table with (tablockx);

3. Открываем два новых сеанса и выполняем в каждом
insert into test2 (value) select 1 where not exists(select 1 from dbo.trigger_table);

4. В сеансе из п. 2 выполняем
commit;

5. В одном из сеансов из п. 3 получим нарушение уникальности ключа.
2 окт 14, 22:11    [16653089]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
invm,

---5. В одном из сеансов из п. 3 получим нарушение уникальности ключа

там у меня unique на поле стоит, и ни одной транзакции не откатилось. Как у вас нарушение уникальности произошло?
2 окт 14, 22:21    [16653150]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Lepsik
Как у вас нарушение уникальности произошло?
Потому что сеансы не ждут один другого и получили параллельно одинаковый результат из getidtest2()
2 окт 14, 22:52    [16653314]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
invm
Lepsik
Как у вас нарушение уникальности произошло?
Потому что сеансы не ждут один другого и получили параллельно одинаковый результат из getidtest2()


у меня ваши запросы отработали нормально, вы тестировали то что написали?
2 окт 14, 23:11    [16653393]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Lepsik
вы тестировали то что написали?
Естественно.
2 окт 14, 23:28    [16653459]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
Как же у вас тогда вставились одинаковые значения если на столбце стоит UNIQUE CONSTRAINT?
2 окт 14, 23:31    [16653468]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Lepsik
Как же у вас тогда вставились одинаковые значения если на столбце стоит UNIQUE CONSTRAINT?
А у меня они и не вставились - в одном из сеансов будет нарушение уникальности ключа.

Но суть не в этом. Суть в том, что ваш метод не гарантирует отсутствия ситуации, когда разные сеансы при вставке в таблицу получат одинаковые значения из getidtest2().
3 окт 14, 00:12    [16653616]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
invm
меня они и не вставились - в одном из сеансов будет нарушение уникальности ключа.


проверил ваши шаги 2 раза - все в порядке, обе вставки сработали

invm
----Суть в том, что ваш метод не гарантирует отсутствия ситуации, когда разные сеансы при вставке в таблицу получат одинаковые значения из getidtest2().


Почему вы так решили?
3 окт 14, 00:27    [16653649]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
invm
Member

Откуда: Москва
Сообщений: 9409
Lepsik
проверил ваши шаги 2 раза - все в порядке, обе вставки сработали
Либо вы что-то не так делаете, либо запросы из п. 3 выполняются последовательно.
Когда оба сеанса из п. 3 висят на ожидании, покажите результата выполнения
select
 r.session_id, t.task_state, t.worker_address
from
 sys.dm_exec_requests r join
 sys.dm_os_tasks t on t.task_address = r.task_address
where
 r.session_id in (<spid1>, <spid2>);

Lepsik
Почему вы так решили?
Тут скорее вопрос к вам - чем именно гарантируется?
3 окт 14, 00:54    [16653724]     Ответить | Цитировать Сообщить модератору
 Re: старый велосипед про генераторы.  [new]
aleks2
Guest
Lepsik
вставлял в 3 потоках по 10000 батчей с единичными инсертами - все хорошо работает, но может что-то не учел?

insert into test2 (value) values (1)


1.
insert test2(value) select 1 union all select 2

2. Если все ограничено "единичными инсертами", то нахрена эти сложности с изготовлением из identity identity+1?
3. Тупая вставка scope_identity даст лучший результат.
3 окт 14, 05:40    [16653879]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить