2011-05-12 13 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

相关问题