Guids vs Auto增量整数

时间:2012-02-02 11:34:26

标签: c# sql-server foreign-key-relationship

我想知道是否有关于处理父母ID的最佳编码实践>代码中的子对象,其中DB记录使用自动递增的int作为ID(在初始保存时)。当然,在代码中你无法猜出这个ID是什么,因此必须将其留空,并且可能在事务中保存所有这些项目首先获取父ID,然后在保存之前将其设置在所有子项上

另一方面,Guids在代码中处理起来要容易得多,因为当然你可以先生成Id并将其设置在所有内容上并保存而不用担心..

是否有一种很简单的方法可以使用auto-ints作为数据库密钥来处理代码中的对象?

感谢

2 个答案:

答案 0 :(得分:31)

GUID似乎是您主键的自然选择 - 如果您真的必须,您可能会争辩将其用于表的PRIMARY KEY。我强烈建议不要使用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相同的问题 - 只是不那么显着。< / p>

然后还有另一个需要考虑的问题:表格上的聚类键也会被添加到表格中每个非聚集索引的每个条目上 - 因此你真的想确保它尽可能小。通常,对于绝大多数表来说,具有2亿行的INT应该足够 - 并且与作为群集密钥的GUID相比,您可以在磁盘和服务器内存中节省数百兆的存储空间。

快速计算 - 使用INT与GUID作为主要和群集密钥:

  • 具有1'000'000行的基表(3.8 MB对15.26 MB)
  • 6个非聚簇索引(22.89 MB vs. 91.55 MB)

TOTAL:25 MB vs. 106 MB - 这只是在一张桌子上!

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

另外:从C#/ .NET的角度来看 - 这取决于您访问SQL Server数据库的方式。如果您使用 Linq-to-SQL Entity Framework v4 之类的内容,您的.NET对象将使用插入的ID自动更新(来自INT IDENTITY列) - 没有你必须做任何事情。所以对我来说,这就是为什么你应该觉得需要使用GUID的原因......

GUID是非常糟糕作为SQL Server群集密钥 - 不仅仅是坏 - 真的,真的, AWFUL

答案 1 :(得分:2)

GUID比汽车公司有一些“编码”优势。

首先它是分离的,你不需要到数据库来获得几乎肯定是唯一的id。

因此,您可以在内存中创建新记录,让它现在知道并将实际存储传递给某些服务,然后愉快地使用它来说明在本地添加相关数据,然后将其传递给相同或其他服务。 像EF这样的东西为你解决的问题是处理必须在db中插入记录然后获得分配给它的DBMS的身份以传递给下游功能。如果你有另一个独特的钥匙并且汽车公司是代理人,你可以避免这种情况,但这不是免费的午餐。

如果我没有进行分发,我的应用程序必须连接到数据库,并且auto inc是一个真正的代理(没有暴露为订单号或一些这样的numptiness),并且int涵盖范围,并且有没有可能说两个或我的客户合并并想要合并他们的数据库,那么我不会打扰guid。

就我而言,应对其中一个是另一个问题。存在一些问题,但与处理您的唯一密钥并不是唯一的相比,它们是微不足道的。