2011-05-12 12 views
3

在SQL Server 2008中,我嘗試從這裏看到的順序與非順序GUID鍵上的聚集索引實驗中重現結果,但我沒有體驗過我期望的插入的顯着加速(以及作者的體驗)。使用連續的GUID可以明顯改善頁面利用率,但由於某些原因,插入10,000行只會快100毫秒(超過10,300毫秒)。在集羣索引上插入順序GUID鍵的速度並不明顯更快

我使用下面的代碼:

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慢。我對此沒有任何解釋。 下面是新的實驗代碼:我看不出

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

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 

頁用法如下,爲什麼這些頁面統計數據(最適合TestInt)並不意味着實驗三是最快的。

+2

你試過運行裏面的插件顯式交易?目前,所有單獨提交的效果可能會支配結果(順便說一句 - 在'GO'之前放置'BEGIN TRAN'很重要,所以最終不會執行10000次,這將需要相同次數的提交'將@@ TRANCOUNT'降到零) – 2011-05-12 11:22:10

+1

機會是你的樣本量只有10000行很少,表格的重新排序需要SQL服務器這麼短的時間,在任何時候你都不會看到太多的東西一個插入。嘗試將其增加到100,000或1,000,000。在處理這種大小的表格時,聚集索引選擇是一個更有意義的選擇。 – JStead 2011-05-12 11:25:51

+0

Kimberly Tripp在她的博客文章中很好地(並且廣泛地)顯示[磁盤空間便宜 - 這不是**點!](http://www.sqlskills.com/BLOGS/KIMBERLY/post/Disk- space-is-cheap.aspx)多麼糟糕的GUID - 隨機或順序 - 與使用「INT IDENTITY」作爲您表上的羣集索引進行比較 – 2011-05-12 11:26:57

回答

2

你可以試試這個修改過的腳本併發布你的結果嗎?

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 
+0

+1 - 我正在研究類似的東西,但你首先得到它,並且更好:) – JNK 2011-05-12 12:59:42

+0

它也可能是一個好的事情來調整數據文件的大小,增加文件可能會歪曲結果 – SQLMenace 2011-05-12 15:43:25

+0

@SQLMenace - 是的,可能會解釋一些時間的變化,但也可以通過我運行的其他應用程序來解釋。 – 2011-05-12 15:49:26

2

自從我寫了原來的博客文章,我決定來運行你的代碼,這裏是我得到

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

記得我與32 GB的RAM和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 
+0

有點令人驚訝!如果你在我的答案中嘗試了代碼,你會得到相同的結果嗎?在你的服務器上,你的'newid()'是否一貫地更快? – 2011-05-12 15:39:01

+0

我剛剛跑過它,見上面 – SQLMenace 2011-05-12 15:40:00

+0

我現在重複了實驗,結果現在(幾乎)符合理論。請參閱我對原始問題表述的擴展。然而,我還擴大了測試覆蓋更緊湊,因此(理論上)更快的方法:順序**整數**鍵。但令我驚訝的是,這比順序的GUID慢。我對此沒有任何解釋。 – someName 2011-05-13 11:03:41

相關問題