【问题标题】:SQL primary key: integer vs varcharSQL 主键:integer vs varchar
【发布时间】:2011-03-10 21:13:58
【问题描述】:

与我合作的团队决定使用 varchar 主键创建一个表。此表被此主键上的另一个表引用。

我有创建整数主键的习惯,遵循我在大学学到的知识。我读到使用整数主键可以提高性能。

问题是我不知道创建整数主键的任何其他原因。你有什么建议吗?

【问题讨论】:

标签: sql performance indexing


【解决方案1】:

VARCHAR 与 INT 的区别不大。重要的是访问模式。

就绝对而言,宽键总是比窄键差。类型绝对不重要,重要的是宽度。但是,与 INT 相比,很少有类型可以在狭窄方面胜过 INT,因此 INT 通常仅凭 4 个字节宽这一事实就胜出。

真正重要的是集群键的选择。经常与主键混淆,两者代表不同的概念,并且不需要重叠。这是更详细的讨论Should I design a table with a primary key of varchar or int? 集群键的选择几乎是表设计中最重要的决定,而在其上机械应用INT identity(1,1) 可能只是一个人可能犯的最大错误。这是访问模式问题的来源:

  • 桌上最频繁的审讯是什么?
    • 投影了哪些列?
    • 应用了哪些谓词?
    • 搜索了哪些范围?
    • 执行了哪些连接?
    • 发生了哪些聚合?
  • 数据是如何插入到表中的?
  • 表格中的数据是如何更新的?
  • 如果有的话,如何从表中清除旧数据?
  • 存在多少个非聚集索引?
    • NC 索引(键或叶)中包含的列多久更新一次?

总的来说,使用 INT IDENTITY 聚簇键可以破坏许多访问模式。因此,在开始应用千篇一律的解决方案之前,可能需要进行一些分析...

一些更一般的准则:

您会看到没有主键设计指南,因为主键不是存储设计的问题,而是建模的问题,并且完全由域驱动。

【讨论】:

  • 我认为与我一起工作的开发人员基本上根据您写下的内容创建了一个 varchar 主键:“主键不是存储设计问题,而是建模问题,并且完全由域驱动”我的意思是:我同意实体标识符是否是字符串(然后,它取决于模型设计),但我不同意您对域进行建模然后将其迁移到数据库上。我希望在我的模型上使用实体 id 作为字符串,在我的数据库中使用 int 主键和唯一的 varchar 键(对应于实体 id)
【解决方案2】:

主键应该代表行的标识,不应随时间改变。

我假设 varchar 是某种自然键 - 例如实体名称、电子邮件地址或序列号。如果您使用自然键,则有时可能会发生键需要更改的情况,例如:

  • 数据输入错误,需要修复。
  • 用户更改了他们的姓名或电子邮件地址。
  • 管理层突然决定必须将所有客户参考编号更改为另一种格式,原因对您来说似乎完全不合逻辑,但即使您解释了它将给您带来的问题,他们仍坚持进行更改。
  • 甚至可能一个国家或州决定更改其名称的拼写 - 不太可能,但并非不可能。

通过使用代理键,您可以避免因必须更改主键而导致的问题。

【讨论】:

  • 我将此标记为答案,只是因为你是第一个给我另一个理由的人。谢谢标记
  • 这是一个旧的,但你在哪里找到“不应该随时间改变”的条款?据我所知,没有什么可以说它应该是恒定的。
  • @Asken 你是对的,但可能会有很多记录(在其他表中)引用该主键。要更改主键,您还需要更改对它的每个引用。
  • 很好的建议。如果一个值有一些外部含义,它最终可能需要改变,使其成为主键的不受欢迎的候选者。
  • 再一次,如果它具有外部含义,则无需通过自然属性查找它,如果仅将其用作主键,则无需对该属性进行额外索引。关于对更改自然键的保留 - 通常假设一个业务逻辑就足够了,其中自然键的更改意味着它是一个完全不同的对象,这通常也是......自然的。
【解决方案3】:

我有点失望,因为我已经 创建整数主节点的习惯 关键(按照一些老师所说的 我在大学)。我读了很多 性能文件 使用整数主键提升。

有一个术语:confirmation bias:

“也称为确认性偏见或 myside 偏见)是人们倾向于支持证实他们的先入之见或假设的信息,而不管它们是否真实。这导致人们选择性地收集新证据,以有偏见的方式解释证据,或选择性地从记忆中回忆信息。”

当然,您的第一反应会是:“但这不是真的!”是的,你会说'因为你有偏见;)[舌头牢牢嵌入脸颊]

这里有一个经典的例子:假设你的动物学教授告诉你所有的天鹅都是白色的,果然,你和你的朋友遇到的所有天鹅都是白色的。现在让我们说在以后的生活中,一位同事表达了这样一种观点,即也许有黑天鹅这样的生物。什么?!那不是你被教导的。你的世界被震撼了!你立即出去进行天鹅调查,你数了数 1000 只白天鹅和零只黑天鹅。证明!如果你发现了 10,000 只白天鹅,那么“所有天鹅都是白色的”假设会正确十倍,对吧?

另一种方法是暂时忘记白天鹅并尝试寻找黑天鹅。也许在阳光明媚的海边度假Dawlish

我真的不想听起来不尊重;你承认阅读了很多关于你被告知的内容,这确实赢得了我的尊重。所以这是一个挑战:尝试找出不需要向表中添加整数列的情况。

这里有一些提示和剧透: 未被其他表引用的表;单列“全键”查找表;查询不多的“小”表:)

以下是您可能想调查的其他一些相关主题:

“主键”中的“主键”一词是否有很多含义,或者给定表中的所有键都相等?

“好”钥匙的品质是什么? (例如,键的值应该是不可变的还是稳定性“足够好”?)

是否将整数列作为人工键(可能是因为可用的自然键不够“好”)或作为代理键(也许是为了提高原本“好”的自然键的性能)添加到表中?

当基于性能的原因将代理键添加到表中时,这是为了实际测量效果还是仅仅为了感知效果(即过早优化)?

代理键应该出现在逻辑业务模型中还是仅用于实现?

总是做某事(例如向表中添加一个整数列)而不每次都让大脑参与是个好主意吗? ;)

[免责声明:我是一个天生的关键倡导者,并避免代理。对我来说,它们就像非规范化:你只在必要时才这样做,通常是针对性能问题(具体和可证明的),故障出在其他地方(糟糕的 SQL 产品版本、目前无法修复的逻辑设计缺陷等) )。代理不应该出现在逻辑业务模型中。我有时需要一个人工标识符,甚至公开了它们的逻辑业务模型。]

【讨论】:

  • +1 用于适当的参考确认偏差 :)
  • 这是一个写得很好,发人深省的答案。它成功地让我对我在 sql 表中几乎自动应用人工键的问题三思而后行。干得好!
  • 计算中确认偏差的另一个例子:40 天密码到期。故事发生在 VAX 计算机的时代,有人发现计算机需要 40 多天才能暴力破解密码,因此他们制定了用户必须每 40 天更改一次密码的规则,并且它卡住了。
  • 我想了解更多关于 40 天密码到期和类似情况的信息。建议一个 Reddit 什么的。很抱歉发表了不相关的评论。
猜你喜欢
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 2011-11-26
相关资源
最近更新 更多