Guid主键/外键两难SQL Server

问题描述:

我面临将我的主键从int身份更改为Guid的两难困境。我会直接解决我的问题。这是一个典型的零售管理应用程序,具有POS和后台功能。有大约100张桌子。数据库与其他数据库同步并接收/发送新数据。Guid主键/外键两难SQL Server

大多数表没有频繁的插入,更新或对他们执行SELECT语句。但是,一些确实频繁插入并选择它们,例如。产品和订单表。

有些表格最多有4个外键。如果我将主键从'int'更改为'Guid',插入或查询具有多个外键的表中的数据时是否会出现性能问题。我知道人们说索引会被分割,16字节是个问题。

空间将不会在我的情况的问题,显然索引碎片也可以照顾使用“NEWSEQUENTIALID()”函数。有人可以告诉我,从那里的经验来看,如果Guid在有许多外键的桌子上会有问题。

我会感到非常的珍惜它你的想法...

GUID似乎是您的主键的自然选择 - 如果您确实需要,您可能会争论将其用于表的主键。我强烈建议不要做是使用GUID列作为集群密钥,默认情况下SQL Server会这样做,除非您明确地告诉它不要。

你真的需要保留除了两个问题:

1)主键是一个逻辑结构 - 候选键唯一和可靠地识别你的表中每一行的一个。这可以是任何东西,真的 - 一个INT,一个GUID,一个字符串 - 选择对你的场景最有意义的东西。

2)聚集键(列或定义表上的“聚集索引”列) - 这是一个物理存储相关的事情,在这里,一个小的,稳定的,持续增长数据类型是您的最佳选择 - INT或BIGINT作为默认选项。

默认情况下,SQL Server表上的主键也用作集群键 - 但这并不需要这样!将以前基于GUID的主键/集群键分解为两个单独的键 - GUID上的主键(逻辑键)和单独的INT IDENTITY上的集群(排序)键(1, 1)栏。

由于Kimberly Tripp - 索引的女王 - 和其他人说一个伟大的多次 - 一个GUID作为聚集键不是最优的,因为由于它的随机性,这将导致大量页面和索引碎片和一般糟糕的表现。

是的,我知道 - 在SQL Server 2005中有newsequentialid()及以上 - 但即使这不是真正的完全顺序,因此也遭受与GUID相同的问题 - 只是稍微突出一点。

然后还有一个需要考虑的问题:表上的聚簇键将被添加到表上每个非聚簇索引中的每个条目上 - 因此,您确实希望确保它小到可能。通常情况下,具有超过250亿行的INT应该足以满足绝大多数表的要求 - 并且与GUID作为集群密钥相比,您可以为磁盘和服务器内存节省数百兆的存储空间。

快速计算 - 使用INT与GUID作为主要和聚集键:

  • 基表与1'000'000行(3.8 MB与15.26 MB)
  • 6个的非聚集索引(22.89 MB与91.55 MB)

总计:25 MB与106 MB - 这只是一个单一的表!

还有一些值得思考的东西 - 金伯利特里普的优秀作品 - 读它,再读一遍,消化它!这真是SQL Server索引福音书。

所以如果你真的必须更改主键的GUID - 尽量确保主键不是聚集键,和在用作群集密钥的表上仍然有一个INT IDENTITY字段。否则,你的表现肯定会下降并受到严重打击。

的使用过的GUID INT缺点:在加入时

字符串值是不作为的表现整数值为最佳,索引和条件。需要比INT更多的存储空间。

生成的GUID应该是(例如,NEWSEQUENTIALID()在SQL 2005)最佳性能部分的顺序,并允许使用聚集索引

更多细节:

http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html

http://blog.sqlauthority.com/2010/04/28/sql-server-guid-vs-int-your-opinion/

+3

在SQL Server中,GUID存储为128位整数,而不是字符串。但是,这仍然是一个整数的4倍。 – 2010-06-08 09:20:59

对于PK使用GUID或int确实取决于场景。从INT到GUID会有性能问题。 GUID是INT的4倍。有一篇关于使用GUID的优点和缺点的文章here

为什么你需要改变整数?

的GUID确实有性能的影响相对于一个整数,但影响可能是最小的取决于你的应用程序,所以没有办法肯定没有测试。我曾经通过一个应用程序从int整理到GUID,并且有一些非常大的表,其中有许多外键,这些表都进行了非常繁重的修改和查询(每天都有成千上万条记录的顺序)。通过分析器,但从用户的角度来看并没有明显的差异。

所以答案是“这取决于”。就像处理表演的所有事情一样,在你尝试之前你无法确定。

我的意思是:在内部使用autoincrement int作为PK,并在用于跨数据库移动行的每个主表上都有一个唯一的Guid列。

在导出数据时加入此列,不导出int并在导入数据时将其映射回int。

特别是在大容量的情况下,int更小更快。