Здравствуйте, 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. Наткнулся на
статью где это хорошо описано.