为什么使用NEWID()比使用NEWSEQUENTIALID()占用更多空间



我正在做一些研究,发现了一个无法解释的异常(我在谷歌上也找不到任何东西)。考虑以下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效率,而且通过扩展,索引也可以减少碎片,总体上更小。

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

相关内容

  • 没有找到相关文章

最新更新