你引用的文章是2002年的,很旧了。只需使用新闻序列ID http://technet.microsoft.com/en-us/library/ms189786.aspx(在 SQL Server 2005 及更高版本中可用)。这保证了您生成的每个新 id 都大于前一个,解决了索引碎片/页面拆分问题。
不过,我想提及的另一个方面是,当您只需要 4 个字节时,使用 16 个字节并不是一个好主意,该文章的作者对此进行了掩饰。假设您有一个表,其中包含 500,000 行,平均 150 字节(不包括聚集列),并且该表有 3 个非聚集索引(在每行中重复聚集列),每个索引依次包含平均 4 字节、25 字节和 50 字节的行不计算聚集列的字节数。
完美 100% 填充因子的存储要求如下(除 % 外,所有数字均以兆字节为单位):
Item Clust 50 25 4 Total
---- ----- ----- ----- ----- ------
GUID 79.1 31.5 19.6 9.5 139.7
int 73.4 25.7 13.8 3.8 116.7
%imp 7.2% 18.4% 29.6% 60.0% 16.5%
在只有一个的非聚集索引中int
4字节列(常见场景),将聚集索引切换为int
使其缩小 60%!这直接意味着表上的任何扫描的性能提高了 60%——而且这是保守的,因为行越小,页面分割发生的频率就会越低,碎片也会保持得更久。
即使在聚集索引本身中,性能仍然提高了 7.2%,这并不是什么都不是的。
如果你用过怎么办GUID
贯穿整个数据库,其中的表具有与此类似的配置文件,其中切换到int
会导致大小减少 16.5%,而数据库本身的大小为 1.397 TB?您的整个数据库将增大 230 GB(请参阅“总计”列,139.7 - 116.7)。这可以转化为现实世界中用于高可用性存储的真金白银。它将您的磁盘采购计划提前,这对您公司的利润有害。
永远不要使用超过必要的数据类型。这就像无缘无故地给你的车增加重量:你will付出代价(如果不是速度,那就是燃油经济性)。
UPDATE
现在我知道您正在客户端代码中创建 GUID,我可以更清楚地看到问题的本质。如果你are能够将 GUID 的创建推迟到行插入时间,这是实现这一目标的一种方法。
首先,为您的系统设置默认值CustomerID
column:
ALTER TABLE dbo.Customer ADD CONSTRAINT DF_Customer_CustomerID
DEFAULT (newsequentialid()) FOR Customer;
现在您不必指定要插入的值CustomerID
in any INSERT
,您的查询可能如下所示:
DECLARE @Name varchar(100) = 'Acme Spy Devices';
INSERT dbo.Customer (Name)
OUTPUT inserted.CustomerID -- a GUID
VALUES (@Name);
在这个非常简单的示例中,您已将一个新行插入到Customer
表,并向客户端返回一个包含刚刚创建的值的行集,所有这些都在一个查询中完成。
如果你想显式插入VALUES (newsequentialid(), @Name)
那也行。