【问题标题】:Database Design Primay Key, ID vs String数据库设计主键,ID 与字符串
【发布时间】:2011-02-02 20:27:45
【问题描述】:

我目前正计划开发一个音乐流媒体应用程序。而且我想知道在服务器上的表中作为主键会更好。一个 ID int 或一个 Unique String。

方法一:

歌曲表: SongID(int), Title(string), *Artist**(string), Length(int), *Album**(string)

类型表 流派(字符串),名称(字符串)

歌曲类型: ***SongID****(int), ***Genre****(string)

方法二

歌曲表: SongID(int)、Title(string)、*ArtistID**(int)、Length(int)、*AlbumID**(int)

类型表 流派ID(整数),名称(字符串)

歌曲类型: ***SongID****(int), ***GenreID****(int)

键:粗体 = 主键,*字段** = 外键

我目前正在使用方法 2 进行设计,因为我相信它会加快查找性能并使用更少的空间,因为 int 占用的空间比字符串少得多。

有什么理由这不是一个好主意吗?有什么需要注意的吗?

【问题讨论】:

    标签: database database-design


    【解决方案1】:

    您做对了 - 身份字段应该是数字而不是基于字符串,这既是为了节省空间又是出于性能原因(在字符串上匹配键比在整数上匹配要慢)。

    【讨论】:

    • 绝对+1。 ID 应该(几乎总是)是一个 INT - 其他任何东西都没有多大意义(除了少数选择情况)
    • -1:这些是做出设计决策的错误原因。根据是否是正确的设计来做出设计决定。然后,如果存在性能问题,请根据需要进行调整和重新设计。
    • 我支持 Max。使用自然键进行设计。这是另一个过早优化的例子。技术密钥有一席之地,但它们不是免费的
    • -1:整数不是一个好的 ID。在您的系统之外,可以有几种不同的方式处理整数,但处理字符串的方式较少。当您跨系统移动数据时,这会使您的 ID 更加健壮(相信有一天您会这样做)。正如 Max 指出的那样,为空间和性能提供整数还为时过早。我相信数值数据类型应该留作计算之用。
    • @Oded 我可能同意你的看法。但我经常在我的空间中看到它,因此也看到了 YMMV。这绝对是一个权衡。我倾向于使用字符串,因为性能或存储将来会成为一个更大的问题吗?可能没有摩尔定律。数据不一致会成为问题吗?是的,因为今天有 x 个系统来处理数据,明天它将是 x + y。如果您说您的系统将永远处于孤岛状态(我打赌不会),那么您对任何事情都很好。不在乎。
    【解决方案2】:

    我的建议是:使用 id。

    您将能够用 20000 首歌曲重命名“流派”而不会破坏任何内容。

    这背后的想法是 id 标识表中的行。无论行有什么在这个问题中都无关紧要。

    【讨论】:

    • 在重命名流派的情况下:您不重命名密钥,而是重命名名称。那也不会破坏任何东西。 ;-)
    • 这将是名为“Disco Dance”的摇滚乐键。不过也没有错。
    • @graffic 我知道我的回复晚了 11 年,但您的示例突出了使用代理键的一个大问题。在你的情况下,正确的做法是用新的“discodance”流派标记歌曲,而不是将摇滚乐键的显示名称更改为“Disco Dance”。否则 Jail House Rock 会怎样?
    【解决方案3】:

    这在很大程度上取决于个人喜好。

    我个人的意见和做法是始终使用整数键并始终使用代理键而不是自然键(因此切勿直接使用社会保险号或流派名称之类的东西)。

    在某些情况下,自动编号字段不合适或无法缩放。在这些情况下,使用 GUID 是有意义的,它可以是数据库中没有本机数据类型的字符串。

    【讨论】:

      【解决方案4】:

      有什么理由这不是一个好主意吗?有什么需要注意的吗?

      是的。如果您需要唯一标识单个数据库之外的相同数据,则整数 ID 非常糟糕。例如,如果您必须将相同的数据复制到具有可能预先存在的数据的另一个数据库系统中,或者您有一个分布式数据库。需要注意的最重要的事情是,像7481 这样的整数在该数据库之外没有任何意义。如果以后您需要扩展该数据库,那么如果不通过手术删除您的数据,这可能是不可能的。

      要记住的另一件事是整数 ID 没有那么灵活,因此它们不能轻易用于特殊情况。互联网协议的设计者明白这一点,并采取预防措施,以某种方式将某些数字块分配为“特殊”(广播 IP、私有 IP、网络 IP)。但这只是可能的,因为有一个围绕这些数字使用的协议。许多数据库不在这样一个定义良好的协议中运行。

      FWIW,这有点像试图确定“强类型”编程范式是否比“弱/动态类型”编程范式更好。这取决于您需要做什么。

      【讨论】:

      • IP 地址是一个特别恰当的例子。它们不再足够大,无法达到预期目的,但它们仍然存在,因为此时更改系统是一项艰巨的任务。
      【解决方案5】:

      从软件的角度来看,GUID 更好,因为它在全球范围内是独一无二的。

      引自:Primary Keys: IDs versus GUIDs

      使用 GUID 作为行标识值感觉更自然——而且 肯定比 32 位整数更真正独特。数据库大师乔 塞尔科seems to agree。 GUID 主键非常适合许多人 开发场景,例如复制,或者当您需要时 在数据库之外生成主键。但这仍然是一个问题 平衡传统 4 字节整数 ID 和 16 字节 GUID:

      GUID 专家

      • 在每个表、每个数据库、每个服务器中都是唯一的
      • 允许轻松合并来自不同数据库的记录
      • 允许在多个服务器之间轻松分发数据库
      • 您可以在任何地方生成 ID,而不必往返数据库
      • 大多数复制方案都需要 GUID 列

      GUID 缺点

      • 比传统的 4 字节索引值大 4 倍之多;这可能会产生严重的性能和存储影响,如果 你不小心
      • 在 userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}' 的地方调试很麻烦
      • 生成的 GUID 应该是部分顺序的,以获得最佳性能(例如,SQL 2005 上的 newsequentialid())并启用 聚集索引

      【讨论】:

      • 这是一个绝妙的答案,@michaelbn!对于大多数数据库,基于整数的唯一 ID 显然是合适的,几十年来我已经在无数应用程序中使用它们。但是,在其他应用程序中,基于文本的 ID 更好。对于我当前的应用程序,基于整数的唯一 ID 已被证明对数据库设计存在问题 - 所以我开始寻找有关基于文本的唯一 ID 的信息。您的回答绝对适合我的需要:我现在确切地知道要采取的方向。谢谢!
      猜你喜欢
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多