B树,数据库,顺序与随机插入和速度.随机赢了

Iam*_*mIC 7 sql sql-server benchmarking clustered-index

编辑

@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
Run Code Online (Sandbox Code Playgroud)

请注意,我没有减去创建GUID的任何时间,没有减去行的相当大的额外大小.我机器上的结果如下:

Int:17,340 ms GUID:6,746 ms

这意味着,在该试验中,16个字节的随机插入更快的近3倍的4个字节的顺序插入.

有人想对此发表评论吗?

PS.我知道这不是一个问题.这是讨论的邀请,这与学习最佳编程有关.

SQL*_*ace 3

翻转操作,int 更快..您考虑过日志和数据文件的增长吗?分别运行每个

declare @i int, @t1 datetime, @t2 datetime

set @t1 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T2 values (NEWID())
    set @i = @i + 1
END


set @t2 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T1 values (@i)
    set @i = @i + 1
end



select DATEDIFF(ms, @t1, @t2) AS [UID], DATEDIFF(ms, @t2, getdate()) AS [Int]
Run Code Online (Sandbox Code Playgroud)

UUID 的问题是当在它们上进行集群而不使用 NEWSEQUENTIALID() 时,它们会导致分页和表碎片

现在尝试这样,你会发现它几乎是一样的

declare @i int, @t1 datetime, @t2 datetime

set @t1 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T2 values (NEWID())
    set @i = @i + 1
END
select DATEDIFF(ms, @t1, getdate()) 

set @t1 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T1 values (@i)
    set @i = @i + 1
end



select DATEDIFF(ms, @t1, getdate())
Run Code Online (Sandbox Code Playgroud)

并逆转了

declare @i int, @t1 datetime, @t2 datetime



set @t1 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T1 values (@i)
    set @i = @i + 1
end

set @t1 = GETDATE()
set @i = 1

while @i < 10000 begin
    insert into T2 values (NEWID())
    set @i = @i + 1
END
select DATEDIFF(ms, @t1, getdate())
Run Code Online (Sandbox Code Playgroud)