编辑
@Remus 纠正了我的测试模式。您可以在下面的答案中看到更正的版本。
我接受了用 DECIMAL(29,0) 替换 INT 的建议,结果是:
十进制:2133
GUID:1836
随机插入仍然获胜,即使行稍大。
尽管解释表明随机插入比顺序插入慢,但这些基准测试表明它们显然更快。我得到的解释与基准不一致。因此,我的问题仍然集中在 b 树、顺序插入和速度上。
...
我从经验中知道,当数据按顺序添加到 b 树时(无论方向如何),它们的性能都很糟糕。但是,当随机添加数据时,可以获得最佳性能。
这很容易用 RB-Tree 之类的东西来演示。顺序写入会导致执行最大数量的树平衡。
我知道很少有数据库使用二叉树,而是使用 n 阶平衡树。我从逻辑上假设它们在顺序输入方面遭受与二叉树相似的命运。
这激发了我的好奇心。
如果是这样,那么可以推断出写入顺序 ID(例如在 IDENTITY(1,1) 中)会导致树发生多次重新平衡。我看到许多帖子反对 GUID,因为“这些会导致随机写入”。我从不使用 GUID,但令我震惊的是,这个“坏”点实际上是一个好点。
所以我决定测试一下。这是我的代码:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[T1](
[ID] [int] NOT NULL
CONSTRAINT [T1_1] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
CREATE TABLE [dbo].[T2](
[ID] [uniqueidentifier] NOT NULL
CONSTRAINT [T2_1] PRIMARY KEY CLUSTERED ([ID] ASC)
)
GO
declare @i int, @t1 datetime, @t2 datetime, @t3 datetime, @c char(300)
set @t1 = GETDATE()
set @i = 1
while @i < 2000 begin
insert into T2 values (NEWID(), @c)
set @i = @i + 1
end
set @t2 = GETDATE()
WAITFOR delay '0:0:10'
set @t3 = GETDATE()
set @i = 1
while @i < 2000 begin
insert into T1 values (@i, @c)
set @i = @i + 1
end
select DATEDIFF(ms, @t1, @t2) AS [Int], DATEDIFF(ms, @t3, getdate()) AS [GUID]
drop table T1
drop table T2
请注意,我并没有减少创建 GUID 的任何时间,也没有减少行的相当大的额外大小。我的机器上的结果如下:
诠释:17,340 毫秒 GUID:6,746 毫秒
这意味着在这个测试中,随机插入 16 字节几乎比连续插入 4 字节快 3 倍。
有人愿意对此发表评论吗?
附言。我知道这不是一个问题。这是一个讨论的邀请,这与学习最佳编程有关。