【问题标题】:Reasons why you wouldn't use a foreign key? [php + MySQL]不使用外键的原因? [php + MySQL]
【发布时间】:2011-01-21 00:38:27
【问题描述】:

我正在开发我的公司用来创建调查的旧 Web 应用程序。我通过 mysql 命令提示符查看了数据库模式,并认为这些表看起来很可靠。虽然我不是数据库专家,但我精通其背后的理论(在我的软件工程课程中参加了一些数据库设计课程)。

话虽如此,我将创建语句转储到 SQL 文件中并将它们导入 MySQL Workbench 并看到它们没有使用任何“实际”外键。它们会像使用 FK 一样存储另一个表的主键,但它们不会将其声明为一个。

所以看到他们的数据库是如何按照我所知道的方式设计的(减去 FK 问题),我想知道这背后可能是有原因的。这是惰性编程的情况,还是您可以通过以编程方式进行所有错误检查来获得一些性能提升?

如果您想要一个示例,他们基本上有调查,而调查有一系列问题。问题是调查的一部分,因此它将其 PK 列在一个列中。差不多就是这样,但他们到处都在使用它。

如果有任何见解,我将不胜感激开始使用它,所以我相信这些人知道他们在做什么)

【问题讨论】:

    标签: php mysql foreign-keys


    【解决方案1】:

    最初的开发者可能选择使用MyISAM 或任何其他不支持外键约束的存储引擎。

    【讨论】:

    • 就是这样。我也许可以在纸上设计一些东西,但我在实践部门肯定缺乏。非常感谢大家:)
    • 顺便说一句,MySQL 从 3.23.44 版本开始支持 InnoDB 的外键。来源:en.wikipedia.org/wiki/MySQL#Future_releases
    • 我使用 MySQL 工作台创建我的架构,然后导出我的语句。我会一直选择 InnoDB 作为我的存储引擎,因此我不知道 MyISAM 根本不支持 FK。
    • 如果你想使用 MySQL 特有的全文搜索功能,你必须使用 MyISAM,它不适用于 InnoDB(或任何其他表类型)......跨度>
    • 这也是我不使用 MySQL 的一个很好的理由。
    【解决方案2】:

    MySQL 只支持在 InnoDB 表上定义实际的外键关系,也许你的是 MyISAM,或者别的什么?

    更重要的是,正确的列上定义了索引(因此应该为持有另一个表的 PK 的列建立索引)。这在 MyISAM 中也是可能的。

    【讨论】:

      【解决方案3】:

      作为一般要点;键可以加快读取速度(如果它们适用于正在发生的读取,它们会帮助优化器)并减慢写入速度(因为它们会增加表的开销)。

      在绝大多数情况下,读取和维护参照完整性的速度提高超过了写入时增加的少量开销。

      缓存、镜像等已经模糊了这种区别,因为大型网站上的大量读取实际上并没有命中“实时”数据库——但这并不是很相关,除非你在亚马逊、Twitter 或类似网站工作.

      【讨论】:

        【解决方案4】:

        在超大型数据库(Teradata 支持的类型)上,您发现它们不使用外键。原因是性能。每次写入数据库时​​,这在数据仓库中通常就足够了,您必须检查表上的所有 fk 的额外开销。如果你已经知道这是真的,那又有什么意义呢。

        在小型数据库上的良好设计只是意味着您将它们放入其中,但将它们排除在外也可以获得性能提升。

        【讨论】:

        • 谢谢。这是我想知道的。我认为他们的数据库中的表数量足够少,因此跟踪“FK”很容易。
        【解决方案5】:

        您实际上不必使用外键。

        如果您没有它们,数据可能会变得不一致,您将无法使用级联删除和更新。

        如果您拥有它们,您可能会因为架构更改而发生的 SQL 语句中的错误而丢失一些用户数据。

        有些人喜欢拥有它们,有些人喜欢没有它们的生活。这两种情况都没有真正的优势。

        【讨论】:

        • 我会说数据一致性是一个真正的优势。
        • @simon,不是真的。您很可能只会有额外的行,这些行不会打扰您,因为它们对大多数查询是不可见的。另一方面,那些隐藏的行可能包含一些对用户至关重要的信息。
        • 但这不仅仅是强制删除废弃的子对象。使用外键强制数据一致性还可以防止许多错误,例如将引用对象的键更改为不存在的值(这种错误在事故发生后通常是不可能或很难纠正的)。如果您认为某些信息应该出于历史目的而存储,那么有比省略外键更好的方法。
        • @simon,当您必须进行循环引用时,它还可以让您免于麻烦。我和他们住了 5 年,没有他们 2 年,坦率地说,我看不出有什么区别。除了我不必考虑应该以什么顺序将数据放入表格中,这样它就不会在我面前爆炸。
        【解决方案6】:

        这是一个真实的例子,我没有使用外键。

        我需要一种方法来存储可能不存在子对象的父子关系,并且子对象是一个抽象类。由于孩子可能有几种类型,我使用一个字段来命名孩子的类型,并使用一个字段来列出孩子的 id。应用程序处理大部分逻辑。

        我不确定这是否是最好的设计决定,但这是我能在截止日期前做出的最好的决定。到目前为止,它运行良好!

        【讨论】:

          猜你喜欢
          • 2014-09-14
          • 2019-10-02
          • 1970-01-01
          • 2018-03-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多