【问题标题】:Sanity Check: Floats as primary keys?健全性检查:作为主键浮动?
【发布时间】:2009-07-09 17:13:56
【问题描述】:

我正在使用旧的 sql server 2000 数据库,将其中的一些信息与我正在构建的新应用程序混合在一起。我注意到几个表中的一些主键是浮点数而不是任何类型的整数。它们不是外键并且都是唯一的。我想不出任何人想让他们的唯一主键 ID 浮动的任何原因,但无论如何我都不是 SQL 专家。所以我想我要问的是,设计这个相当广泛的数据库的人是否知道我不知道的事情?

【问题讨论】:

  • 我相信你的直觉在这里是 100% 正确的;浮点数是坏键。

标签: sql database-design


【解决方案1】:

我目前正在使用一个相当大的会计软件包,其中 350 多个表中的每一个都有一个 FLOAT(53) 的主键。所有实际值都是整数,系统会严格检查它们是否确实是整数(有特殊函数可以完成所有递增工作)。

我确实对这个设计感到好奇,但我可以理解为什么选择它并给它一些功劳。 一方面,系统足够大,可以在某些表中拥有数十亿条记录。另一方面,这些主键必须易于从外部应用程序(如 Excel 或 VB6)中读取,在这种情况下,您并不想将它们设为 BIGINT。

因此,浮动很好。

【讨论】:

  • 这很有趣,你能解释一下你所说的易读是什么意思吗?您的意思是外部应用程序更容易阅读还是人类可读?感谢您的回复。
  • 不,我的意思是那些人们围绕大事编写自己的小助手应用程序的系统,很容易无法处理 64 位整数。 VB6 中没有原生支持 BIGINT 的数据类型,您必须使用 Double(如 Excel 自动建议的那样)或 Variant-Decimal(如 ADO 所做的那样)。这至少是一些东西!我可以很容易地想象一个根本无法使用 BIGINT 的外部系统。
【解决方案2】:

我与一个在 SQL Server 数据库中使用浮点数作为 PK 的人一起工作。如果他坚持使用 INT,他担心标识符的编号会用完。 (在 SQL Server 上为 32 位。)他只是查看了浮点数的范围,并没有考虑这样一个事实,那就是对于较大的数字,由于精度有限,位不包含在数字中。所以他取 MAX(PK) + 1.0 的代码有时会返回一个等于 MAX(PK) 的数字。不好。我最终说服他不要使用 float 作为未来数据库的代理主键。他在修复他正在处理的数据库之前就辞职了。

要回答您的问题,“所以我想我要问的是,设计这个相当广泛的数据库的人是否知道我不知道的事情?”很可能NO!至少在选择数据类型方面不会。

【讨论】:

  • 您开始遇到问题PK+1.0=PK 的数字是 9007199254740992。以每秒 1000000 个新 PK 计算,您需要 285 年才能遇到这个数字。我不认为这是值得担心的一点。另一方面,只有每秒 100 次,您可以在不到一年的时间内用完有符号 int 中的空间。
【解决方案3】:

浮点数有一个有趣的特性:总是可以在其他两个值之间插入一个值,除了比特用完的病态情况。它的缺点是表示问题可能使您无法通过键引用一行;很难使两个浮点值彼此相等。

【讨论】:

  • 原则上,如果你想要这些属性,我认为你总是可以添加一个包含浮点数的索引列,除了 int 主键。
  • 这是我的第一个想法,但我找不到类似的,它们都是连续的 3.0、4.0、5.0 等。也许这是某种未来的证明,虽然我不是很确定为什么,因为它们似乎只是 ID。感谢您的意见。
  • 这听起来不像是针对提问者的具体情况的正确答案......但无论如何你都会被投票给下一个人搜索这个问题的有趣且可能的答案。
【解决方案4】:

它是 NUMERIC(x,y) 格式和 IDENTITY 吗?如果是这样,它可能是从旧版本的 SQL Server 升级而来的。过去的 IDENTITY 只能是 NUMERIC 格式,而不是我们今天使用的常见 INT。

否则,无法判断浮点数是否适合作为主键 - 这取决于您的域。比较起来有点困难(IEEE INT 比浮点数更有效)并且大多数人使用单调递增的数字(IDENTITY),所以整数通常是人们真正想要的。

因为看起来您正在存储整数:

更直接地回答原始问题:如果您要存储整数,请使用整数数据类型。存储和比较效率更高。

【讨论】:

  • 实际上,PK 可以一直是 INT,但由于 BIGINT 不存在,人们使用 NUMERIC
  • 嗯,好的。我知道 Sybase SQL Server - 很久以前 - 只支持 NUMERICS,我认为 SQL Server 6.5 之前的版本继承了该限制
  • 我相信他们从一开始就使用 SQL Server 2000,尽管我不能 100% 确定。不过,我要仔细检查一下。
  • 奇怪的是,MySQL 过去在比较浮点数方面比 int 更快(现在不再是这种情况,我赶紧补充一下),所以一些过早优化的粉丝可能是负责任的。我们这里有一个这样的生产数据库,当我第一次看到一张以浮动为 PK 的桌子时,这让我去查找。
【解决方案5】:

我使用 Cerner Millenium 数据库已经有几年了(实际上它使用了 Oracle)。最初,我很惊讶地看到它使用浮点数作为表上的 ID。然后我在我们的数据库中遇到了一个 ID > 2^32 并且我写的查询给出了错误的结果,因为我错误地将它转换为 INT 我意识到他们为什么这样做。我没有发现任何反对在现实世界中使用浮点数的论据,对于键,您只需要“略大于”2^32 的数字,并且 ID 的值始终采用 #### 形式##.0。 (没有人谈论 ######.###### 形式的 ID。)但是,现在我们正在将此数据导入 SQL Server 仓库,并且 bigint 可用,我们将继续用 bigint 而不是 float。

【讨论】:

    【解决方案6】:

    仅供参考——还有另一种看法:

    我从事实时过程控制工作,因此,我的大多数行条目都是基于时间的,并且由非 ASCII 机器以高速率自动生成。时间——这是我的用户通常搜索的内容,而我的许多“用户”实际上本身就是机器。因此,基于 UTC 的主键。

    【讨论】:

      猜你喜欢
      • 2011-03-03
      • 1970-01-01
      • 2011-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 2015-04-10
      相关资源
      最近更新 更多