Падение производительности на 10% (?)

Кто нибудь может подтвердить или опровергнуть мои результаты?

При навешивании пустого триггера на простую таблицу я получил падение производительности в операциях с таблицей порядка 10%.

IF exists (select * from sysobjects where name='origtbl_test' and xtype='U')
DROP table [dbo].[origtbl_test]

-- Delimiter
GO

CREATE TABLE [dbo].[origtbl_test](
[RowID] [uniqueidentifier] PRIMARY KEY,
[InstanceID] [uniqueidentifier] ,
[name] char(256)
)
GO

IF exists (select * from sysobjects where name='origtbl' and xtype='U')
DROP table [dbo].[origtbl]

-- Delimiter
GO

CREATE TABLE [dbo].[origtbl](
[RowID] [uniqueidentifier] PRIMARY KEY,
[InstanceID] [uniqueidentifier] ,
[name] char(256)
)
GO

IF NOT OBJECT_ID('[dbo].[origtbl_DelTrg]') IS NULL
DROP TRIGGER [dbo].[origtbl_DelTrg]

--Delimiter
GO

CREATE TRIGGER [dbo].[origtbl_DelTrg] ON [dbo].[origtbl]
FOR DELETE
AS
BEGIN
declare @i int
END

--Delimiter

С уважением
Игорь

Forums: 

Ничего

Ничего удивительного, за все нужно платить :)
А на выполнении какого(ких) конкретно запроса(ов) получено 10% ?
Я получал от 4% до 13% на удалении 10тыс в цикле...

Изображение пользователя ipanshin.

это грабеж

Запрос простой
insert into origtbl(rowid,name) select newid(),'bla-bla'
vs.
insert into origtbl_test(rowid,name) select newid(),'bla-bla'

имхо, это не плата, это грабеж. Триггер то пустой. А если я вставлю туда, скажем insert..., то я получу еще худшую картину: 40% падение производительности.

Курсоры есть, но я ими не могу пользоваться так как я должен заплатить.
Теперь триггера есть, но я ими также не могу пользоваться так как я должен заплатить временем работы пользователя.

А вот за числа 4% и 13% спасибо.

FOR DELETE?

> insert into ...
а триггер то FOR DELETE...

> origtbl vs. origtbl_test
из-за uniqueidentifier данные в этих таблицах разные => разное распределение, фрагментация, количество страниц/экстендов и т.п.
чтобы "усреднить", нужно увеличить количество записей...

> А вот за числа 4% и 13% спасибо.
прошу прощения, это было на "холодном" сервере и при небольшом кол-ве записей, сейчас, когда он "разогрелся", и при увеличении количества удаляемых записей, разницы практически никакой нет...

Изображение пользователя ipanshin.

>а триггер то FOR

>а триггер то FOR DELETE...
триггера присутствуют на таблице все (for delete, for insert, for update) мне приходится реализовывать конструкцию output ... inti tblaudit ... на триггерах

>"усреднить",
мои 10% и есть усредненные результаты. М.б. репрезентативность выборки мала, но число 9.7% довольно стабильно держится.
>прошу прощения
А можно "практически никакой нет..." сказать в цифре 0% или 0.01% ?

%-т подсчитайте сами :)

> А можно "практически никакой нет..." сказать в цифре 0% или 0.01% ?

set nocount on
go
declare @dt datetime; set @dt=getdate()
insert into origtbl_test(rowid,name) select top 10000 newid(), a.name+b.name from master..sysobjects a, master..sysobjects b
while @@rowcount>0 begin
delete origtbl_test where rowid=(select top 1 rowid from origtbl_test)
end
print datediff(ms,@dt,getdate())
go 3
declare @dt datetime; set @dt=getdate()
insert into origtbl(rowid,name) select top 10000 newid(), a.name+b.name from master..sysobjects a, master..sysobjects b
while @@rowcount>0 begin
delete origtbl where rowid=(select top 1 rowid from origtbl)
end
print datediff(ms,@dt,getdate())
go 3

-------------------------------
Beginning execution loop
10576
11750
11483
Batch execution completed 3 times.
Beginning execution loop
10706
10563
10486
Batch execution completed 3 times.

Изображение пользователя ipanshin.

Похоже на правду

Я получил следующие результаты. Немного поменял, что несущественно. Единственно я запускаю сравниваемые скрипты в разных окнах и делаю ситуацию, когда сиквел делал нечто другое. То есть не даю сиквелу настроиться на операцию заранее. Это видимо самое важное.

declare @dt datetime
insert into origtbl_test(rowid,name) select top 10000 newid(), a.name+b.name from master..sysobjects a, master..sysobjects b

set @dt=getdate()
while @@rowcount>0 begin
delete origtbl_test where rowid=(select top 1 rowid from origtbl_test)
end
select datediff(ms,@dt,getdate())
go 3

Это уже мои результаты
14343
14796
14513

15936 11%
15856 7%
14186 -2%

И по моей оценке

insert into origtbl(rowid,name) select top 10000 newid(), a.name+b.name from master..sysobjects a, master..sysobjects b

DECLARE @StartDate datetime, @EndDate datetime, @i int
SET @i = 0
print convert(varchar,getdate(),109)
SET @StartDate = GETDATE()

WHILE @i < 10000
BEGIN

delete [dbo].[origtbl]
where rowid=(select top 1 rowid from [dbo].[origtbl])

SET @i = @i + 1
END
set @EndDate = getdate()
SELECT (DATEPART(ms, @EndDate)+ DATEPART(s, @EndDate)*1000 + DATEPART(mi, @EndDate)*60000)
- (DATEPART(ms, @StartDate) + DATEPART(s, @StartDate)*1000 + DATEPART(mi, @StartDate)*60000)

go 3
-- out tr
14657
13717
15297
------
15687 7%
15550 13%
14626 -4%
---------
То есть не дешево. Любой интерпретирующий подход при всей его простоте страдает тем, что он дорог.

Адвокат дьявола

Тест с точки СУБД "ужасный", поэтому потери производительности следует считать приемлемы в таких условиях.
Он искуственный, потому что удаление в цикле из таблицы подряд большого кол-ва записей - это плохой стиль SQL программирования. Такие циклы нужно преобразовывать в запросы.

Изображение пользователя ipanshin.

это же оценка производительности

Важно, что в двух тестах одинаковый код. Такие циклы нужны, чтобы оценить время выполнения операции на одной строке. Важна разница, а не абсолютное значение времени выполнения. Поэтому все в порядке и триггер на самом деле недешевое удовольствие и губит производительность всей системы в целом. Как вша. А если триггеров много, то и вшей много и БД больше чешется, а не выполняет полезную работу. она может вообще заболеть тифом.

Опаньки

Триггер объявленный для DELETE, тормозит вставку в таблицу. Да уж ...

--declare @i int

А вот с таким триггером какое будет падение? У меня почти нет...
CREATE TRIGGER [dbo].[origtbl_DelTrg] ON [dbo].[origtbl]
FOR DELETE
AS
BEGIN
--declare @i int
return
END