为什么数据库设计者不会使IDENTITY列从最小值而不是1开始?

时间:2012-08-29 11:32:41

标签: sql sql-server database database-design

我们知道,在Sql Server中,IDENTITY (n,m)表示值将从n开始,增量值为m,但我注意到所有数据库设计者都会生成Identity列为IDENTITY(1,1),没有利用来自(-2,147,483,648) to (2,147,483,647)的所有int数据类型的值,

我计划将所有标识列设为IDENTITY (-2,147,483,648, 1),(标识列对应用程序用户是隐藏的)。

这是个好主意吗?

7 个答案:

答案 0 :(得分:55)

如果您发现20亿个值还不够,那么您将发现40亿还不够(在项目的整个生命周期中需要超过任何的两倍) ,它最初的设计,并不罕见*),所以你需要完全采取不同的方法(可能是长值,可能是完全不同的东西)。

否则你只是变得陌生而且无法获得。

此外,谁没有他们知道的数据库,例如项目312是否具有测试特定事物的一些很好的特性?我知道我脑子里有一些任意的ids。他们可能会称之为“他们两次命名这么好”,但我总是将纽约称为“657城市,涵盖了我们的大部分测试案例”。这只是一个简写,但-2147482991不会那么方便。

*添加一点。有些事情,你可能会说“啊约100”,发现它实际上是110,好吧。与其他人一起,实际上你会发现它实际上只有10万 - 你已经达到了数量级。数字越大,这种错误就越频繁,因为这种问题最终导致数十亿的估计与那些最终得到数十个答案的估计不同。如果您估计在给定的情况下200是您的最大值,那么您应该留出可能还有几百个空间。如果你估计在特定情况下有20亿,你应该留出几千万亿的空间。也就是说,我唯一一次看到有人真的开了一个零下20亿的身份证,他们最终有大约3000行。

答案 1 :(得分:9)

在SQL Server端,负ID可以正常处理,就像正数一样处理,所以你可以这样做。

其他人是对的,您应该考虑不同的建议,但主要问题是连接到您的数据库的应用程序。

让我们来看看MS环境。这是一个例子: .NET DataSet autoincremented id-s上使用否定ID -s来跟踪代码中的更改。所以你可能会遇到麻烦,因为:

否定键用于行的临时实例。

以下是参考:MSDN

因此,在MS环境中为MSSQL设计这样的数据库并不是一个好主意。

答案 2 :(得分:9)

如果您的代码中有一个代表您的表的类(很可能会发生这种情况),那么每次创建新对象时,默认情况下都会为其分配ID 0。如果已经分配了ID 0,则可能导致覆盖数据库中的数据的错误。这样,只需执行if (myObject.ID != 0)

即可轻松确定对象是否为新对象或是否来自数据库

答案 3 :(得分:5)

使用接近于零的整数的“好”副作用之一是它们易于使用,易于开发人员,测试人员等,尤其是在调试和单元测试时。

此外,代理键具有悄悄进入商业术语的习惯,例如:用户可能会看到位于浏览器顶部的URL查询字符串中的PK - 数字越多,他们就越有可能在帮助台查询中错误引用某些内容。

所以这就是为什么我很高兴我的身份在1,而在-2147483231,而且,正如@Jon建议的那样,移动到BIGINT任何时候我可能需要超过20亿行。

答案 4 :(得分:5)

当您从负数转换为正数时,您将越过零。这意味着(假设您实际上插入了几十亿行),最终您的标识符为零。这本身并不坏,但可能会为ORM工具提供一个潜在的边缘情况,或者只是简单的应用程序代码,难以区分零和零。

答案 5 :(得分:4)

负面ID可用于在实时环境中进行测试,其中虚拟数据需要与实际数据混合用于测试目的,然后在测试完成后进行处理。这应该只有很好的理由 - 我只使用过一次技术。

在单行只读表中,负ID也可用于管理员目的(即,没有事务,表上没有可执行的SQL运行)。

除了这些特定目的,同一性值<= 0将产生比光更多的热量。

答案 6 :(得分:0)

根据MS Docs(https://docs.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/implementing-identity-in-a-memory-optimized-table?view=sql-server-2014)的说法,只需添加即可,内存优化表支持IDENTITY(1,1)。但是,内存优化表不支持定义为IDENTITY(x,y)且x!= 1或y!= 1的标识列。

因此,我认为,以及其他用户提到的其他原因,IDENTITY(1,1)对于内存优化的表更实用且内存效率更高。

从INT IDENTITY(1,1)开始,然后在达到极限后,可以按照以下步骤“升级”到BIGINT:

  1. 放弃当前PK约束:    ALTER TABLE [dbo]。[tbName]删除约束[PK_tbName_Id]    开始
  2. 将PK升级到BIGINT:    ALTER TABLE [dbo]。[tbName] ALTER COLUMN [dbo.Id] BIGINT

  3. 重新创建PK约束:   ALTER TABLE [dbo]。[tbName]添加约束[PK_tbName_Id]主键   丛集   (     [Id] ASC   )

希望这会有所帮助,很幸运!