【问题标题】:Auto incrementing ID as primary key on all tables自动递增 ID 作为所有表的主键
【发布时间】:2017-06-08 15:11:13
【问题描述】:

我正在为一个使用 MySQL 的电子商务网站设计一个数据库。我已经列出了必要的表格列表以及表格所需的所有字段。我一共有 9 张桌子。

我所做的是在所有表上包含一个自动递增的 ID 作为主键。

除了 2 之外,我的所有表都归一化为 3NF。两个表“用户”和“出口”未标准化为 2NF。

在此过程中,我意识到使用自动递增 ID 作为主键时,规范化很麻烦。由于不严格要求规范化,我想知道在所有表上使用自动递增 ID 作为主键是否有任何缺点?

【问题讨论】:

标签: mysql sql database design-patterns database-design


【解决方案1】:

在我的时间里,我创建了很多表。我只在其中 1/3 中使用了AUTO_INCREMENT。其余的似乎是“完美的‘自然’PK”,所以我就这样走了。

“范式”是一种教科书式的入门方法。在现实生活中(在我看来),NF 后来在性能和其他考虑方面退居二线。

对于 InnoDB 表,您确实应该有一个 explicit PRIMARY KEY(auto_inc 或 natural)。

正如 Renzo 指出的那样,auto_inc 减慢速度的通用模式是多:多映射表,我在这里讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

在 InnoDB 中,PRIMARY KEY 与数据一起存储(集群),因此索引结构(BTree)几乎不占用额外空间。每个二级索引占用一个单独的 BTree,隐含包含 PK 列。

【讨论】:

    【解决方案2】:

    在所有表中使用自动递增的 ID 作为主键很好。这将帮助您自动索引数据。如果您计划向我们提供任何 ORM(例如 Doctrine2),您必须需要每个表的主键。

    【讨论】:

    • 哪个 ORM 要求您在所有表中使用自动递增键?我知道有人鼓励它,但我不知道任何 ORM 也不允许自然键和复合键。那将是一个非常有限的框架。
    • 正如我在重播 Doctrine2 中提到的,更喜欢每个实体的身份。当我们要从数据库中生成实体时,doctrine2 必须需要标识列。
    • Doctrine 2.1 支持复合主键,并且不需要自增键。 docs.doctrine-project.org/projects/doctrine-orm/en/latest/…
    【解决方案3】:

    您的问题已标记为 MySQL,因此我将指出 MySQL 的 InnoDB 存储引擎使用主键作为所有表的聚集索引。

    如果可能,通过聚集索引进行查询会更有效。但是,如果您有一个任意规则,即所有表必须使用自动增量主键,即使有另一列或一组列可以用作主键,并且您始终运行查询搜索这些列而不是自动-increment 列,那么您将永远无法获得通过聚集索引查询的优势。

    【讨论】:

      【解决方案4】:
      【解决方案5】:

      我同意@Arun。使用 UUID 而不是自动递增的 INT ID。这允许更好地缓存数据库写入。如果您创建新记录,他们将需要一个新 ID。如果 ID 由 DB 分配,则逻辑层必须首先与 DB 对话以获取新增加的 ID。 UUID 可以由逻辑层甚至前端生成,无需与 DB 对话。是的,它使用了更多字节,但将图层与数据库分开这一事实在我的书中是一个胜利

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-13
        • 2020-09-01
        • 2015-05-11
        • 2016-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多