40

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

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

这是一个好主意吗 ?

4

7 回答 7

55

如果你发现 20 亿的价值还不够,你会发现 40 亿也不够(在项目的整个生命周期内需要比最初设计的多两倍以上的任何东西,这几乎是稀有*),因此您需要完全采用不同的方法(可能是长值,可能是完全不同的东西)。

否则,您只会变得陌生和难以理解,没有任何收获。

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

*补充一点。有些事情你可能会说“啊,大约 100”,然后发现它实际上是 110,好吧。与其他人一起,您会发现实际上它实际上是 100,000 - 您超出了数量级。数字越高,这种错误就越多,因为最终估计数十亿的问题与最终得到数十亿答案的问题不同。如果您估计 200 是给定情况下的最大值,那么您可能应该留出空间再增加几百个。如果您在给定情况下估计 20 亿,您可能应该多留出几万亿的空间。也就是说,我唯一一次看到有人实际上以负 20 亿开始 id,他们最终有大约 3,000 行。

于 2012-08-29T11:35:50.700 回答
9

如果您的代码中有一个代表您的表的类(这很可能会发生),那么每次您将创建一个新对象时,默认情况下都会为其分配 ID 0。如果已经分配了 ID 0,则可能导致覆盖数据库中的数据的错误。这也可以很容易地确定一个对象是否是新的,或者它是否来自数据库,只需执行if (myObject.ID != 0)

于 2012-08-29T14:33:06.877 回答
9

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

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

假设以 MS 环境为例。下面是一个示例: .NET DataSet在自动递增的 id-s 上使用负 ID -s来跟踪代码中的更改。所以可能你会遇到麻烦,因为:

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

这是参考:MSDN

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

于 2012-08-29T11:50:51.360 回答
5

使用接近于零的整数的“好”副作用之一是它们易于使用,并且易于开发人员、测试人员等记住,尤其是在考虑调试和单元测试的情况下。

此外,代理键有一个潜入业务术语的讨厌习惯,例如,用户可能能够在浏览器顶部的 URL 查询字符串中看到 PK - 数字中的数字越多,他们就越有可能错误引用某些内容在帮助台查询中。

所以这就是为什么我很乐意将我的身份设置为 1 而不是-2147483231 的原因之一,相反,正如@Jon 所建议的那样,BIGINT我可能需要超过 2的任何时间我的表中有十亿行。

于 2012-08-29T11:46:15.920 回答
5

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

于 2012-10-17T20:10:33.927 回答
4

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

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

除了这些特定目的之外,标识值 <= 0 会产生比光更多的热量。

于 2012-09-05T00:02:29.660 回答
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] DROP CONSTRAINT [PK_tbName_Id] GO
  2. 将 PK 升级到 BIGINT: ALTER TABLE [dbo].[tbName] ALTER COLUMN [dbo.Id] BIGINT

  3. 重新创建 PK 约束: ALTER TABLE [dbo].[tbName] ADD CONSTRAINT [PK_tbName_Id] PRIMARY KEY CLUSTERED ([Id] ASC)

希望这会有所帮助,祝你好运!

于 2019-02-18T23:11:33.607 回答