gpt4 book ai didi

sql-server - 为什么使用 NEWID() 比 NEWSEQUENTIALID() 使用更多空间?

转载 作者:行者123 更新时间:2023-12-02 20:17:20 24 4
gpt4 key购买 nike

我正在做一些研究,我遇到了一个无法解释的异常情况(而且我在 Google 上找不到任何信息)。考虑以下 SQL:

CREATE TABLE MyGuid (
ID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID()
)
GO
CREATE TABLE MyGuidSeq (
ID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWSEQUENTIALID()
)
GO

DECLARE @i INT, @noRecords INT
SET @noRecords = 1000000

-- MyGuid
SET @i = 1
WHILE (@i <= @noRecords)
BEGIN
INSERT INTO MyGuid DEFAULT VALUES
SET @i = @i + 1
END

-- MyGuidSeq
SET @i = 1
WHILE (@i <= @noRecords)
BEGIN
INSERT INTO MyGuidSeq DEFAULT VALUES
SET @i = @i + 1
END

exec sp_spaceused 'MyGuid', true
exec sp_spaceused 'MyGuidSeq', true

结果:

Table name  No. Rows   Reserved Space  Actual space  Index Size  Unused Space
MyGuid 1,000,000 34,760 KB 34,552 KB 160 KB 48 KB
MyGuidSeq 1,000,000 24,968 KB 24,768 KB 176 KB 24 KB

问题

任何人都可以解释为什么使用 NEWSEQUENTIALID() 而不是 NEWID() 时保留/实际空间要小得多吗?

回应答案

我运行了以下测试来检查 Luaan 给出的答案:

CREATE TABLE MyGuid (
ID UNIQUEIDENTIFIER DEFAULT NEWID()
)
GO
CREATE TABLE MyGuidSeq (
ID UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID()
)
GO

DECLARE @i INT, @noRecords INT
SET @noRecords = 1000000
-- MyGuid
SET @i = 1
WHILE (@i <= @noRecords)
BEGIN
INSERT INTO MyGuid DEFAULT VALUES
SET @i = @i + 1
END

-- MyGuidSeq
SET @i = 1
WHILE (@i <= @noRecords)
BEGIN
INSERT INTO MyGuidSeq DEFAULT VALUES
SET @i = @i + 1
END

exec sp_spaceused 'MyGuid', true
exec sp_spaceused 'MyGuidSeq', true

不同之处在于我删除了主键(意味着该表现在是一个堆表)。现在这两个表的大小完全相同。这证明该表是通过其聚集索引进行物理组织的。

name       rows    reserved  data      index_size  unused
MyGuid 1000000 25992 KB 25976 KB 8 KB 8 KB
MyGuidSeq 1000000 25992 KB 25976 KB 8 KB 8 KB

最佳答案

这与分区有关。基本上,newId() 将以随机顺序创建 GUID,这意味着您始终插入到表的中间。另一方面,顺序 ID 总是附加到表的末尾,这要简单得多。

如果你想了解更多,可以看看分页上的一些资料。一个好的开始可能是关于 MS SQL 分页的官方 MSDN 页面 - http://technet.microsoft.com/en-us/library/ms190969(v=sql.105).aspx

您还必须了解,行本质上是按存储数据库数据的物理文件中的 ID 组织的。 ID 之间没有空格的文件(例如使用标识列且不删除时)可以占用更少的空间来存储相同数量的数据。

我预计数据库的完全收缩将显着减少 MyGuid 表中因碎片而丢失的空间量,而对 MyGuidSeq 大小的影响很小。

如果您可以使用顺序 GUID,那就这样做 - 它们可以大大提高 INSERT 效率,并且通过扩展,索引也可以减少碎片,整体更小。

您没有显示“花费的时间”调试输出,但我希望这些输出也有显着不同(尽管这可能会被数据库可用的内存所抵消 - 它不需要改变立即数据文件;如果您想了解更多信息,请查找有关事务日志的内容)。

关于sql-server - 为什么使用 NEWID() 比 NEWSEQUENTIALID() 使用更多空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20974062/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com