不对主键使用自动递增编号的原因

Nic*_*ick 17 sql-server primary-key

我正在处理其他人的数据库,其中主键是通过查找表生成的,该表包含表名列表和最后使用的主键.存储过程会增加此值并在将其返回到调用"插入"SP之前检查它是唯一的.

使用这样的方法(或仅生成GUID)而不仅仅使用身份/自动号码有什么好处?

我不是在谈论实际上意味着像ISBN或产品代码这样的主键,而只是唯一的标识符.

谢谢.

Gal*_*ian 27

在您使用复制的情况下,自动生成的ID可能会导致问题(因为我确定您找到的技术可以!).在这些情况下,我通常会选择GUID.

如果您不太可能使用复制,那么自动递增PK很可能会正常工作.


Gre*_*ter 17

使用自动编号没有任何内在错误,但有几个原因没有这样做.尽管如此,正如dacracot所提到的,滚动自己的解决方案并不是最好的主意.让我解释.

不在每个表上使用自动编号的第一个原因是您可能最终合并来自多个表的记录.假设您有一个销售订单表和一些其他类型的订单表,并且您决定提取一些常见数据并使用多个表继承.拥有全球唯一的主键是很好的.这类似于bobwienholt关于合并数据库的内容,但它可以在数据库中发生.

其次,其他数据库不使用这种范例,而其他范例如Oracle的序列则更好.幸运的是,可以使用SQL Server模拟Oracle序列.一种方法是为整个数据库创建一个名为MainSequence的AutoNumber表,或者其他任何东西.数据库中没有其他表将使用自动编号,但任何需要自动生成主键的人都将使用MainSequence来获取它.通过这种方式,您可以获得dacracot所讨论的所有内置性能,锁定,线程安全等,而无需自己构建它.

另一个选择是使用GUID作为主键,但我不建议这样做,因为即使你确定一个人(甚至是一个开发人员)永远不会阅读它们,有人可能会,而且很难.更重要的是,事情在T-SQL中很容易被隐含地强制转换为内容,但是隐式地转换为GUID会有很多麻烦.基本上,它们很不方便.

在构建新系统时,我建议使用专用表来生成主键(就像Oracle序列一样).对于现有的数据库,我不会忘记改变它.


and*_*hky 10

来自CodingHorror:

GUID优点

  • 每个表,每个数据库,每个服务器都是唯一的
  • 允许轻松合并来自不同数据库的记录
  • 允许跨多个服务器轻松分发数据库
  • 您可以在任何地方生成ID,而不必往返数据库
  • 大多数复制方案无论如何都需要GUID列

GUID缺点

  • 它比传统的4字节索引值大4倍; 如果你不小心,这可能会产生严重的性能和存储影响
  • 调试很麻烦(其中userid ='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • 生成的GUID应该是部分顺序的以获得最佳性能(例如,SQL 2005上的newsequentialid())并允许使用聚簇索引

本文提供了很多关于GUID与自动增量决策的良好外部链接.如果可以,我会使用GUID.


dac*_*cot 6

递增的过程方法必须是线程安全的.如果没有,您可能无法得到唯一的数字.此外,它必须很快,否则将成为应用程序的瓶颈.内置函数已经考虑了这两个因素.


Jon*_*eet 6

客户端能够预先分配一大堆ID来执行批量插入,而不必使用插入的ID更新其本地对象,这对客户非常有用.然后是Galwegian提到的整个复制问题.


小智 5

我对自动递增键的主要问题是它们缺乏任何意义

在我看来,这是主键的要求——除了标识记录之外没有其他存在的理由。如果它没有现实世界的意义,那么它就没有现实世界的理由去改变。一般来说,您不希望主键发生更改,因为您必须搜索替换整个数据库或更糟。令我感到惊讶的是,有些事情我本以为是独一无二的、不会改变的,但几年后却发现事实并非如此。


小智 5

这是使用自动递增整数作为键的东西:

您必须先发布该记录,然后才能访问该记录。这意味着,在您发布记录之前,您无法准备将存储在另一个表中的相关记录,或者由于许多其他可能原因之一访问新记录的唯一性可能有用。 id,在发布之前。

以上是我决定采用一种方法还是另一种方法的因素。