INSERT с последовательным ключом GUID в кластерном индексе не значительно быстрее - PullRequest
3 голосов
/ 12 мая 2011

В SQL Server 2008 я пытался воспроизвести результаты экспериментов с кластеризованным индексом для последовательных и непоследовательных ключей GUID, которые можно увидеть здесь http://sqlblog.com/blogs/denis_gobo/archive/2009/02/05/11743.aspx, но я не испытываю значительного ускорения вставок, которое я бы сделаложидаем (и автор переживает).Использование страницы явно улучшено благодаря последовательному идентификатору GUID, но по некоторым причинам вставка 10000 строк происходит всего на 100 мс быстрее (из 10 300 мс).

Я использую следующий код:

CREATE TABLE TestGuid1 (Id UNIQUEIDENTIFIER not null DEFAULT newid(),
SomeDate DATETIME, batchNumber BIGINT)

CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER not null DEFAULT newsequentialid(),
SomeDate DATETIME, batchNumber BIGINT)

CREATE CLUSTERED INDEX ix_id1 ON TestGuid1(id)
CREATE CLUSTERED INDEX ix_id2 ON TestGuid2(id)

go

SET NOCOUNT ON
INSERT TestGuid1 (SomeDate,batchNumber) VALUES (GETDATE(),3)
go 10000

SET NOCOUNT ON
INSERT TestGuid2 (SomeDate,batchNumber) VALUES (GETDATE(),3)
go 10000

DBCC showcontig ('TestGuid1') WITH tableresults
DBCC showcontig ('TestGuid2')  WITH tableresults

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate))
FROM TestGuid1
GROUP BY batchNumber

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate))
FROM TestGuid2
GROUP BY batchNumber

Может кто-нибудь объяснить, почему я не испытываю более значительного ускорения для вставок в TestGuid2?

Последующие действия : Как было предложено в теме ниже, я расширил тест:результаты тестов имеют тенденцию к значительным изменениям во времени, поэтому теперь эксперименты повторяются N раз, и сообщается общее и среднее использование времени.Я также добавил третий тест, а именно для первичных ключей в последовательных целочисленных столбцах.Это должен быть самый быстрый и самый компактный из всех трех методов, поскольку целочисленный тип меньше, а IDENTITY (1,1) является (или, по крайней мере, должен) быть быстрым.По крайней мере, по моей интуиции.Среднее время выполнения теперь выгодно для последовательного GUID, но неожиданно вставки в третьем эксперименте (с последовательными целочисленными ключами) на медленнее , чем последовательные GUID.У меня нет объяснения этому.Вот код для новых экспериментов:

SET NOCOUNT ON

CREATE TABLE TestGuid1 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

CREATE TABLE TestInt (Id Int NOT NULL identity(1,1) PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000


WHILE (@BatchCounter <= 20)
BEGIN 
BEGIN TRAN

DECLARE @LocalCounter INT = 0

    WHILE (@LocalCounter <= @NumRows)
    BEGIN
    INSERT TestGuid1 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
    SET @LocalCounter +=1
    END

SET @LocalCounter = 0

    WHILE (@LocalCounter <= @NumRows)
    BEGIN
    INSERT TestGuid2 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
    SET @LocalCounter +=1
    END

SET @LocalCounter = 0

    WHILE (@LocalCounter <= @NumRows)
    BEGIN
    INSERT TestInt (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
    SET @LocalCounter +=1
    END

SET @BatchCounter +=1
COMMIT 
END

DBCC showcontig ('TestGuid1') WITH tableresults
DBCC showcontig ('TestGuid2')  WITH tableresults
DBCC showcontig ('TestInt')  WITH tableresults

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWID()]
FROM TestGuid1
GROUP BY batchNumber

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWSEQUENTIALID()]
FROM TestGuid2
GROUP BY batchNumber

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [IDENTITY()]
FROM TestInt
GROUP BY batchNumber

DROP TABLE TestGuid1
DROP TABLE TestGuid2
DROP TABLE TestInt

И среднее время выполнения:

NEWID()            3064
NEWSEQUENTIALID()  1977
IDENTITY()         2223

Использование страницы выглядит следующим образом:

Table          Pages  AveragePageDensity
----------------------------------------
TestGuid1      50871  68,4
TestGuid2      35089  99,2
TestInt        32259  98,7

Я не понимаю, почему эта статистика страниц (которые лучше всего подходят для TestInt) не означает, что эксперимент третий является самым быстрым.

Ответы [ 2 ]

2 голосов
/ 12 мая 2011

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

3   8726  -- newid()
3   12550 -- newsequantialID 

Помните, что я запускаю это на сервере с 32 ГБ ОЗУ и 8 процессорами, а не на ноутбуке

на моей локальной машине я почти не вижу разницы между двумя

Помните, что кроме вставок чтение будет намного медленнее, потому что таблица фрагментирована

Вот что я получаю при запуске скрипта Мартина на сервере

batchNumber NEWID()
17  1696
19  1706
14  1680
16  1706
5   1660
6   1890
7   1650
8   1663
13  1673
15  1683
2   1656
9   1673
20  1750
1   2033
3   1673
10  1673
12  1670
4   1650
11  1690
18  1696

batchNumber NEWSEQUENTIALID()
2   1276
9   1260
20  1290
13  1266
15  1280
17  1266
19  1266
5   1260
6   1266
7   1260
8   1260
1   1243
3   1256
10  1270
12  1263
14  1266
16  1276
4   1256
11  1270
18  1270

Вот что происходит на моем рабочем столе, файлы не имеют размера BTW

batchNumber NEWID()
1   9470
2   4446
3   5996
4   3860
5   4170
6   2403
7   3283
8   3573
9   1883
10  3980
11  2580
12  2780
13  1643
14  2836
15  3250
16  4303
17  3250
18  3376
19  8723
20  2616

batchNumber NEWSEQUENTIALID()
1   2566
2   1336
3   1256
4   3123
5   3023
6   1166
7   2396
8   1180
9   2386
10  3896
11  3790
12  3066
13  1396
14  2010
15  1183
16  3110
17  4060
18  4260
19  1896
20  2013
2 голосов
/ 12 мая 2011

Можете ли вы попробовать этот измененный сценарий и опубликовать результаты?

    SET NOCOUNT ON

    CREATE TABLE TestGuid1 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY,
    SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

    CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
    SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

    DECLARE @BatchCounter INT = 1

    WHILE (@BatchCounter <= 20)
    BEGIN 
    BEGIN TRAN

    DECLARE @LocalCounter INT = 0

        WHILE (@LocalCounter <= 100000)
        BEGIN
        INSERT TestGuid1 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
        SET @LocalCounter +=1
        END

    SET @LocalCounter = 0

        WHILE (@LocalCounter <= 100000)
        BEGIN
        INSERT TestGuid2 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
        SET @LocalCounter +=1
        END

    SET @BatchCounter +=1
    COMMIT 
    END

    DBCC showcontig ('TestGuid1') WITH tableresults
    DBCC showcontig ('TestGuid2')  WITH tableresults

    SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWID()]
    FROM TestGuid1
    GROUP BY batchNumber

    SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWSEQUENTIALID()]
    FROM TestGuid2
    GROUP BY batchNumber

DROP TABLE TestGuid1
DROP TABLE TestGuid2

Я вижу довольно дико различающиеся результаты между отдельными прогонами (на моем ноутбуке, а не на сервере!), Но есть определенная тенденция к увеличению скорости последовательного запуска..

NEWID() Среднее 5168,9

batchNumber          NEWID()
-------------------- -----------
1                    4270
2                    2480
3                    2706
4                    3333
5                    7480
6                    5346
7                    4306
8                    7713
9                    7313
10                   4760
11                   4680
12                   4113
13                   3433
14                   2686
15                   4963
16                   8040
17                   5313
18                   8160
19                   9533
20                   2750

NEWSEQUENTIALID() Среднее 3000,85

batchNumber          NEWSEQUENTIALID()
-------------------- -----------------
1                    2016
2                    1820
3                    1886
4                    1870
5                    4873
6                    3473
7                    3730
8                    3690
9                    1983
10                   2020
11                   1906
12                   5596
13                   2100
14                   1950
15                   2096
16                   1876
17                   5196
18                   2110
19                   2113
20                   7713
...