在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)并不意味着实验三是最快的。
你试过运行里面的插件显式交易?目前,所有单独提交的效果可能会支配结果(顺便说一句 - 在'GO'之前放置'BEGIN TRAN'很重要,所以最终不会执行10000次,这将需要相同次数的提交'将@@ TRANCOUNT'降到零) – 2011-05-12 11:22:10
机会是你的样本量只有10000行很少,表格的重新排序需要SQL服务器这么短的时间,在任何时候你都不会看到太多的东西一个插入。尝试将其增加到100,000或1,000,000。在处理这种大小的表格时,聚集索引选择是一个更有意义的选择。 – JStead 2011-05-12 11:25:51
Kimberly Tripp在她的博客文章中很好地(并且广泛地)显示[磁盘空间便宜 - 这不是**点!](http://www.sqlskills.com/BLOGS/KIMBERLY/post/Disk- space-is-cheap.aspx)多么糟糕的GUID - 随机或顺序 - 与使用“INT IDENTITY”作为您表上的群集索引进行比较 – 2011-05-12 11:26:57