使用项目特定前缀和自动编号作为主键?

12

今天早上我们开了一个会,讨论如何在我们正在制作的数据库中存储某些资产的 ID, 讨论有点激烈,所以我决定向 SO 的专家请教。

我认为我们应该有如下表结构(简化版本):

示例1)

  • AssetId - int(32) - 主键
  • Type - 字符串

因此一些示例数据如下:

==AssetId======Type===
  12345        "Manhole"
  155415       "Pit"

另一个团队成员建议类似以下这样:

示例 2)

  • AssetId - 字符串 - 主键
  • Type - 字符串

因此,一些示例数据如下:

==AssetId======Type===
  "MH12345"    "Manhole"
  "P155415"    "Pit"

我们会对类型进行简短的版本处理,然后将其附加在ID前面并存储到数据库中。我见过一些资产数据库采用这种方法,但从未真正喜欢它。

出于排序原因,我不太喜欢使用字符串作为ID。此外,当你已经拥有了资产类型时,我觉得这样做只是为了存储无用信息。

您会采取什么方法?为什么?采用方法1是否有任何优势?

编辑:是的,我将在方法1中使用AUTO_INCREMENT。


看起来有几个答案 - 包括当前被接受的答案 - 将示例2误解为自然主键,即包含实际业务数据的键。也许您可以稍微澄清一下这一点,因为示例2中的键似乎只是代理键 - 没有与行的业务数据相关联 - 但具有附加的表特定前缀。 - Hans-Peter Störr
9个回答

26
通常的经验法则是:不要在主键中使用有意义的信息(例如社会安全号码或条形码),只使用自增整数。即使数据看起来很恒定,也可能在某个时刻发生变化(例如新法规出台导致所有社会安全号码重新计算)。

3
是的!在我曾经工作过的三家公司中,由于某些白痴选择了“自然”键,造成了很多痛苦。UPC会被回收利用;并非每个人都有社会安全号码;人们在创建SKU时会出错。你可以存储它,你可以将其设为唯一值,但PK是你关系的秘密编号。你不要暴露它。 - Nicholas Piasecki
1
我认为这个答案甚至没有回答问题。他并没有提出自然键,而是一个带有前缀的代理键,告诉它属于哪个表。;-) - Hans-Peter Störr

7

这是关于代理键和自然键的决策,前者是代理(或“技术”)键,后者是自然键。

我得出的结论是,几乎总是应该使用代理键。如果使用自然键,它们可能会更改,更新主/外键通常不是一个好主意。


这是一个有趣的观点,但它并没有回答问题,因为示例1和示例2都是代理键。;-) - Hans-Peter Störr

4
我会选择前者。创建唯一的ID应该留给SQL服务器,如果它们是字符串,你无法以线程安全的方式自动创建它们。据我了解,你必须自己处理这个问题?

速度是另一个因素。处理int值总是比处理字符串快。我认为在索引方面有其他性能优势,一个比我更懂SQL的人可以详细解释。

根据我的经验,使用字符串ID会失败。


3

出于性能考虑,我会选择使用数字作为主键。整数比较要比字符串比较便宜得多,并且在数据库中占用的空间更少。


3

我想提出一些观点和建议:

  • 考虑单独为类型创建一个表,例如包含Id和Desc列,并在该表中添加一个外键TypeId。为了规范化,进一步执行操作。但这可能并不理想。如果您认为它有用,请进行操作。

  • 如果您将来考虑向UUID转移,则将其设置为字符串是有意义的。然后您无需更改数据类型。

[编辑]

我同意Cletus的观点。在一些实际项目中,这个代理键证明是有益的。它们允许更改,并且您很清楚,变化是唯一不变的。


2
我个人认为第一种方法要好得多。它允许数据库软件进行简单的整数比较来查找和按键排序,这将提高表操作性能(例如SELECT,复杂的JOIN,按键索引查找等)。
当然,我假设无论哪种方式,您都使用某种自动递增方法来生成ID - 无论是序列,AUTO_INCREMENT还是类似的东西。请帮我一个忙,不要在程序代码中构建它们,好吗?

是的,我将在方法1中使用AUTO_INCREMENT。(添加到帖子中) - Nathan W

1

我更喜欢示例1,因为你提到的原因。唯一我能想到使用示例2的理由是如果你正在尝试适应现有数据库中的字符串ID(非常常见),但即使在这种情况下,我仍然更喜欢使用以下方法。

==AssetId(PK)==Type========DeprecatedId====
  12345        "Manhole"   "MH64247"
  155415       "Pit"       "P6487246"

0
唯一的优点是,仅通过主键就可以轻松地确定该键适用于哪个表的哪一行。这个想法很好,但它是否有用取决于您的日志记录和错误消息策略。它可能会有性能劣势,因此除非您能够列出某些具体使用它的原因,否则我不会使用它。
(您也可以通过使用全局序列生成数字键或使用不同的数字范围、最后几位数等来获得此优势。然后您就不会有性能劣势,但也许您不会轻易找到该表。)

0

如果您的资产已经具有唯一的自然标识符(例如带有员工ID的员工),请使用它们。创建另一个唯一标识符没有意义。

另一方面,如果没有自然唯一ID,请使用尽可能短的ID,以确保预期表大小有足够的唯一键(例如整数)。它将需要更少的磁盘空间,可能会更快。此外,如果您发现自己后来需要使用基于字符串的键,则可以进行简单的替换操作:

  • 向资产表添加字符串主键。
  • 向引用表添加字符串外键。
  • 使用整数关系更新字符串关系的简单UPDATE命令。
  • 为字符串列添加外键约束。
  • 删除整数列的外键约束。
  • 完全删除整数列。

在特定的DBMS上,这些步骤中的一些可能会出现问题,可能需要卸载/重新加载表以删除整数主键列,但基本上需要采取这种策略。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接