Re[10]: [MSSQL 2005]Instead of trigger, как вернуть identity
От: Ziaw Россия  
Дата: 18.06.08 19:56
Оценка:
Здравствуйте, Niteshade, Вы писали:

N>Здравствуйте, Ziaw, Вы писали:


Z>>Вот это как раз голословно. Я аргументирую свою точку зрениия, а вы просто говорите, что вас не волнуют эти проблемы. Это ваше право, но контраргументов нет.

N>какие, простите, контраргументы?
N>Вас попросили привести пример метаданных и запроса, которые бы проиллюстрировали Вашу точку зрения
N>Вы их не привели
N>о каких аргументах тогда речь?)
Я не понимаю, почему надо доказывать, что вдвое или вчетверо больший размер ключа увеличивает I/O, особенно это заметно на таблицах в которых отношение данных к ссылкам на другие таблицы невелико, например many-to-many.

Проведем синтетический тест
тестовые таблицы:
CREATE TABLE dbo.GuidFields(
    id uniqueidentifier NOT NULL,
    ref1 uniqueidentifier NOT NULL,
    ref2 uniqueidentifier NOT NULL,
    ref3 uniqueidentifier NOT NULL
)
CREATE TABLE dbo.IntFields(
    id int NOT NULL,
    ref1 int NOT NULL,
    ref2 int NOT NULL,
    ref3 int NOT NULL
)
ALTER TABLE dbo.GuidFields ADD CONSTRAINT PK_GuidFields PRIMARY KEY (id) 
CREATE NONCLUSTERED INDEX IX_GuidFields ON dbo.GuidFields  (ref1 ASC)
CREATE NONCLUSTERED INDEX IX_GuidFields_1 ON dbo.GuidFields  (ref2 ASC)
CREATE NONCLUSTERED INDEX IX_GuidFields_2 ON dbo.GuidFields  (ref3 ASC)
ALTER TABLE dbo.IntFields ADD CONSTRAINT PK_IntFields PRIMARY KEY CLUSTERED (id) 
CREATE NONCLUSTERED INDEX IX_IntFields ON dbo.IntFields (ref1 ASC)
CREATE NONCLUSTERED INDEX IX_IntFields_1 ON dbo.IntFields (ref2 ASC)
CREATE NONCLUSTERED INDEX IX_IntFields_2 ON dbo.IntFields (ref3 ASC)

заполняем случайными данными по 500к записей.

запросы:
/* сравнение индексных полей, сравниваются все поля, цель полное чтение всех индексов */
select count(1) from table where ref1 < ref2 or ref2 < ref3 or ref1 > ref3


результат:

select count(1) from IntFields where ref1 < ref2 or ref2 < ref3 or ref1 > ref3
-----------
     500000
(1 rows affected)
Table 'IntFields'. Scan count 1, logical reads 1553, physical reads 3, read-ahead reads 1549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 125 ms,  elapsed time = 431 ms.

select count(1) from GuidFields where ref1 < ref2 or ref2 < ref3 or ref1 > ref3
-----------
     500000

(1 rows affected)
Table 'GuidFields'. Scan count 1, logical reads 4563, physical reads 3, read-ahead reads 4559, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 203 ms,  elapsed time = 1009 ms.

Отлично виден втрое больший I/O.

/* доступ к части индекса */
select count(1) from table where ref1 < (select top 1 ref1 from IntFields order by id)
select count(1) from table where ref1 > (select top 1 ref1 from IntFields order by id)


select count(1) from IntFields where ref1 < (select top 1 ref1 from IntFields order by id)
select count(1) from IntFields where ref1 > (select top 1 ref1 from IntFields order by id)
-----------
     462429
Table 'IntFields'. Scan count 2, logical reads 636, physical reads 3, read-ahead reads 629, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 78 ms,  elapsed time = 297 ms.
-----------
      37570
(1 rows affected)
Table 'IntFields'. Scan count 2, logical reads 58, physical reads 0, read-ahead reads 51, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 35 ms.


select count(1) from GuidFields where ref1 < (select top 1 ref1 from GuidFields order by id)
select count(1) from GuidFields where ref1 > (select top 1 ref1 from GuidFields order by id)
-----------
     295357
(1 rows affected)
Table 'GuidFields'. Scan count 2, logical reads 1291, physical reads 3, read-ahead reads 1285, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
   CPU time = 47 ms,  elapsed time = 333 ms.
-----------
     204642
(1 rows affected)
Table 'GuidFields'. Scan count 2, logical reads 897, physical reads 0, read-ahead reads 889, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
   CPU time = 31 ms,  elapsed time = 187 ms.

Опять разница IO в 3 раза.

При любом запросе, кроме index seek небольшого количества значений это будет заметно.

Планы приводить не буду, они тут тривиальные и абсолютно одинаковые для обеих таблиц.
скрипты создания тестовой базы и теста

Случай когда GUID'ы действительно хороши, это репликация. Генерить ключи на клиенте в других случаях никакого смысла нет.

P.S. Наткнулся на статью где это хорошо описано.
perfomance размер записи размер индекса