数据库中的自动增量功能

时间:2010-11-02 07:16:27

标签: asp.net mysql sql-server database sql-server-2005

我使用SQL Server,当我创建一个新表时,我将特定字段设置为自动增量 首要的关键。问题是有些人告诉我,当删除任何记录(它们不关心自动增量字段编号)时,字段是主键的自动增量,字段在某些时候增加 - 如果我的字段的类型是例如整数 - 整数范围将被完全消耗,我将遇到麻烦。所以他们告诉我不要再使用这个功能了。

最好的解决方案是通过获取主键的最大值来完成代码,然后如果值不存在,则最大值为1其他明智的max + 1

有关此问题的任何建议吗?我可以使用自动增量功能吗?

我还想知道不喜欢使用自动增量的情况......以及替代方案......

注意::这个问题一般不是特定于任何DBMS,我想知道这对于DBMS如ORACLE,Mysql,INFORMIX也是如此....

非常感谢。

5 个答案:

答案 0 :(得分:11)

您应该使用标识(自动增量)列。 bigint数据类型可以存储值最多2 ^ 63-1 (9,223,372,036,854,775,807)。即使您插入和删除大量记录,我认为您的系统不会很快达到此值。

如果您正确实施了建议的方法,最终会遇到很多锁定问题。否则,您将不得不处理因约束违规而引发的异常(或者更糟糕的是 - 非唯一值,如果没有主键约束)。

答案 1 :(得分:8)

SQL Server中的int数据类型可以保存-2,147,483,648到2,147,483,647之间的值。

如果您使用-2,147,483,648种植您的身份列,例如FooId identity(-2,147,483,648, 1)然后你有超过40亿的价值观。

如果你真的认为这仍然不够,你可以使用bigint,它可以保持-9,223,372,036,854,775,808到9,223,372,036,854,775,807的值,但这几乎可以保证是过度的。即使使用大量数据和/或大量事务,在使用int时耗尽标识值之前,您可能会耗尽磁盘空间或耗尽应用程序的生命周期,而且几乎可以肯定bigint

总而言之,你应该使用一个标识列,你不应该关心值中的空白,因为a)你有足够的候选值,b)它是一个没有逻辑意义的抽象数。

如果您要实现您建议的解决方案,使用导出下一个标识列的代码,您将不得不考虑并发,因为您必须同步访问两个竞争事务之间的当前最大标识值。实际上,您可能最终会导致显着的性能下降,因为您必须首先读取最大值,计算然后插入(更不用说同步并发事务所涉及的额外工作)。但是,如果使用标识列,则数据库引擎将为您处理并发性。

答案 2 :(得分:3)

继续在SQL Server中使用PK身份功能。在mysql中,还有自动增量功能。不要担心你用完整数范围,在此之前你将耗尽硬盘空间。

答案 3 :(得分:3)

他们建议的解决方案可能并且很可能会产生并发问题和/或可伸缩性问题。如果两个会话使用您同时描述的Max技术,它们可以提供相同的数字,然后两者都尝试同时添加它。这将创建约束违规。

您可以通过锁定表或捕获异常来解决该问题,并继续重新插入..但这是一种非常糟糕的做事方式。锁定会降低性能并导致可伸缩性问题(如果您计划的记录数量太多以至于担心溢出int,那么您将需要可伸缩性)。

标识字段是原子操作。两个会话无法创建相同的标识字段,因此使用它时不存在此问题。

如果您担心标识字段可能会溢出,请使用更大的数据类型,例如bigint。你很难生成足够的记录来溢出它。

现在,有正当理由不使用身份字段,但这不是其中之一。

答案 4 :(得分:1)

我会建议AGAINST使用身份/自动增量,因为:

  • SQL Server 2005/2008中的实现已中断。 Read more

  • 如果要使用ORM将数据库映射到对象,则效果不佳。 Read more

如果您通常通过程序访问数据库并且不依赖于手动向DB发送插入语句,我建议您使用Hi / Lo生成器。您可以在第二个链接中阅读更多相关信息。