2012-02-02 59 views
11

我想知道是否有一个最好的编码实践中处理代码中的父>子对象的ID,其中数据库记录使用自动递增的int作为ID(在初始保存)。当然,在代码中,您无法猜测此ID可能是什么,因此必须将其保留为空,并且可能会将所有这些项目保存在交易中,然后将其保存在所有孩子中,然后再保存它们。Guids vs Auto增加整数

另一方面,Guids更容易在代码中处理,因为当然,您可以高兴地生成Id并将其设置为一切,并且不必担心。

是否有处理对象的简单方法在代码中使用自动ints作为他们的数据库密钥?

感谢

回答

29

的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 vs. 106 MB - 这只是一张桌子!

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

另外:从一个C#/。NET点 - 这取决于你如何访问SQL Server数据库。如果您使用类似于Linq-to-SQL实体框架v4,您的.NET对象将自动更新插入的ID(从您的INT IDENTITY列) - 没有你必须做任何事情。所以对我来说,少了一个理由,为什么你应该感到需要使用GUID的....

GUID的是可怕的坏作为SQL Server群集键 - 不只是坏 - 真的,真的,AWFUL

+0

+1从我这里一个真正的好解释。谢谢marc_s – Jehof 2012-02-02 11:46:23

+0

对那些对这些问题缺乏深入了解的人非常有帮助,比如我自己:-) – diggingforfire 2012-02-02 11:47:43

+0

我已经对我的前任使用Guid作为集群密钥而犯了错误,并且不会自己犯这个错误:)我没有使用linq -sql或实体框架..也许这是值得一看。因为这些表格并不是真的会受到抨击,因为这可能是Guids是前进的方向,只是试图摆脱它们,除非我真的必须......因此问是否有一种巧妙的使用整数的方式。 。非常感谢你的有用答案和时间..想知道如果有人能够从.net方面多回答这个问题..? – nat 2012-02-02 12:32:44

2

GUID与auto incs有几个“编码”优势。

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

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

如果我没有做分布式,我的应用程序必须连接到数据库,并且auto inc是一个真正的代理(没有公开作为订单号或某种这样的numptiness),并且int覆盖了范围,并且那里没有可能说两个人或我的客户合并并想要合并他们的数据库,那么我就不用费心去指导。

就我而言,应对另一个问题。有一些问题,但与处理独特的密钥相比,它们是微不足道的。