代码之家  ›  专栏  ›  技术社区  ›  Tim Lytle

单个自动编号而不是多个键

  •  2
  • Tim Lytle  · 技术社区  · 15 年前

    是否有理由对主键使用一个递增字段,而不是实际表示唯一记录的多个字段?

    我正在开发一个现有的PHP应用程序,所有表似乎都有一个“id”键,而不是使用两个或更多字段,这些字段实际上是记录特有的(如用户、拍卖、出价)。

    我不是数据库专家,但对我来说,这似乎很懒惰(或缺乏经验)。是否有任何好处(性能或其他方面)?

    更新的 :我不是指PSUDO唯一数据(SSN、电子邮件地址等),您可能希望确保数据真正唯一。我说的是具有明显的外键引用的表,但不是将这些引用与表本身的唯一字段一起使用,而是每个表都有一个递增的ID。

    不想开始一场主观的辩论,这对我来说是没有意义的。

    10 回复  |  直到 13 年前
        1
  •  5
  •   lavinio    15 年前

    使用合成主键有几个优点:

    • 您可以更改关键字段中的值,而无需执行索引更新操作。
    • 索引较小
    • 它使外键关系更简单
    • 既然您不处理字符串,就不会有编码问题

    数据库通常围绕使用单调递增的键构建索引进行特定的优化。

    也就是说,偶尔进行一点非规范化并没有什么问题。如果用例是清晰的,并且表相对较小,那么做一些方便的事情。

        2
  •  5
  •   Mitchel Sellers    15 年前

    这取决于“唯一”的定义。是的,名称、电子邮件地址和SSN值应该是“唯一的”。然而,发生了一些奇怪的事情。有一个单独的ID值,在很多情况下,可以使生活更容易…

    更新

    根据对问题的编辑,我并不觉得有什么需要。听起来你的处境是这样的。一个“联接表”,在这里您只需创建一个从一个表到另一个表的uniqueid的关联。

    我认为您所说的一个简单的例子是用户角色关联。必须将用户与角色关联。一个用户ID和一个角色ID。

    数据库中的结构类似于

    MappingId (Your Auto Number) (This is the PK)
    UserId (From the user table)
    RoleId (From the Role table)
    

    这个结构对我来说没有意义,我只需要用户和roleid组成主键,因为这里不需要重复条目。

    如果你有什么不同的东西可以改变事情…

        3
  •  3
  •   Powerlord    15 年前

    哦,天哪,看来我们又开始了关于自然与替代钥匙的大辩论了。

    最简单的原因是防止数据冗余。自然键往往需要多个键,这些键可能会在数据库的生命周期中发生更改。

    例如,如果一个人结婚并更改了姓氏,那么该姓氏必须在其引用的任何地方更新。

    如果将外键设置为on update cascade,这不是问题,因为数据库会为您做这些。

    随着表的嵌套越来越深,您可能会发现键需要越来越多的列。我实际上看到了一个表,它有一个七列主键。对于只有其他四列的表。

        4
  •  1
  •   Community CDub    8 年前

    通常需要在主键上使用聚集索引。有一个复合的、集群的、主键的问题是,当插入新行时,SQL必须将新记录插入到其他记录之间,这意味着要洗牌。此外,主键越大,存储它所需的空间就越大。

    Here 是一篇关于使用guid作为主键的文章,但对于复合键也是如此。

    也看到 this great answer .

        5
  •  0
  •   Peter    15 年前

    好吧,这个ID给数据库从1到无穷大的顺序排序。用户名等都是暂时的,并不总是按顺序排列的。所以,可能会使搜索速度更快。另外,您似乎建议使用多个键表示一个项目。这通常会减慢速度,因为现在必须检查两件事,以确保某件事是正确的,而不是一件事。

        6
  •  0
  •   northpole    15 年前

    下面是一些使用自动编号的要点

    • 自动编号是一个唯一的键 建立外交关系 更易于维护和使用

      自动编号是数字,所以很容易使用,而且不会弄乱 他们起来了。我的意思是,如果你 主键是一个字符串, 开发人员忘了把它放进去 单引号会破坏你的 性能

      使用自动编号是正常的标准做法。

      您仍然可以使其他字段“唯一”

      使用自动编号重置序列要容易得多。

      如果您需要在序列中跳到前面,使用 数量大于属性组合,或 串

    只是一些事情…

        7
  •  0
  •   Javier    15 年前

    在大多数情况下,当这些字段真正唯一地标识由记录表示的实体时,实际上并不清楚。一次又一次地,我看到了一些案例,旧的数据库概念在商业思想中根深蒂固,阻碍了任何进一步的发展。

        8
  •  0
  •   richardtallent    15 年前

    我在数据库中尝试过的几乎每一个“自然”键组合都会随着时间的推移而变得不唯一。随着抽象的泄漏,数据模型需要快速发展。

    其中包括姓名、电话号码、SSN、法律文件参考、页码、电子邮件地址、用户名、项目编号,以及我在职业生涯中尝试使用的其他一些东西。

    除此之外,其他关于写新记录、比较外键等性能的答案就足够了。

    您可以保留当前的唯一性业务逻辑,而不必将其烘焙到主键中——只需在自然键列上设置一个唯一索引。和任何索引一样,插入和更新都要付出代价,但如果它碰巧也是 有用的 索引(有助于覆盖一些查询)更好。

        9
  •  0
  •   WolfmanDragon    15 年前

    归根结底,这取决于数据结构的“正常”程度。根据定义,高度规范化的数据库只能有用于主键的单个字段。在这种情况下,几乎没有理由使用序列号或自动生成的数字作为pk。数据结构应该用唯一的条目设计为pk(跟踪人是一个问题,只有这么多的名字)。

    当然,标准化会带来性能损失,因此数据库会被取消标准化以使其可用(对于Web应用程序非常常见)。对于高度非规范化的数据库,很多时候不使用表中的每个字段就不可能获得pk。请记住,结构非规范化的原因是为了提高性能。我熟悉的所有数据库都为每个pk构建一个索引。索引越大,维护索引的开销就越大。

    构建巨大的索引会破坏插入和更新时间性能,使去规范化变得毫无用处(除非它是只读数据库)。搜索巨大的索引也需要更长的时间,并且比较小的索引使用更多的内存。

    在夏季,对于需要多个字段才能获得唯一的pk的任何表,自动生成pk通常有利于提高性能。

        10
  •  0
  •   Bob Mc    13 年前

    是的,这将引发辩论。

    一般来说,主键数据应该是不可变的,在使用从表数据派生的自然键时,情况往往不是这样。如前所述,像ssn这样的东西经常可以改变,从而摆脱不可变性。

    单调增加的代理键,如“自动编号”或“标识”列,是自然键的简单替代品。但是,它们可能容易出现索引效率低下的情况,因为它们在B-树型索引算法中可能不太平衡。这可以通过在MS SQL Server中使用随机生成的代理项(如uniqueidentifier,即guid)来解决,但我已经了解到这也会影响性能。

    通常,我使用从连续特性(如自动编号或标识)生成的代理键来简化表连接。