代码之家  ›  专栏  ›  技术社区  ›  Manu JCasso

外键是否会影响查询性能

  •  17
  • Manu JCasso  · 技术社区  · 15 年前

    据我所知 this post 在某些情况下,外键可以提高查询性能。

    不过,我听到了相反的说法,因为引用完整性检查,外键实际上会损害查询性能。在什么情况下(如果有的话),这是真的?


    1)术语查询似乎具有误导性。我对各种绩效惩罚感兴趣。

    2)对于插入、删除或更新语句的负面影响,是否有人有任何实际数字(我知道这取决于具体的系统,但无论如何,任何实际测量都会受到赞赏)?

    11 回复  |  直到 9 年前
        1
  •  13
  •   Dean J    15 年前

    我假设对于插入查询,约束(包括外键约束)会稍微降低性能。数据库必须检查您告诉它要插入的内容是否是您的约束允许它插入的内容。

    对于select查询,外键约束不应对性能进行任何更改。

    由于插入几乎总是非常快,所以很少的额外时间不会被注意到,除非是在边缘情况下。(构建一个几千GB的数据库,您可能希望禁用约束,然后在以后重新启用,只要您确定数据是好的。)

        2
  •  19
  •   melkisadek    15 年前

    如果引用完整性需要一个外键,那么该外键的存在应该构成性能的基线。

    如果你不把座位放进去的话,你也可以问一个问题:一辆外形良好的车包括座位,而一个外形良好的数据库包括外键。

        3
  •  5
  •   marc_s    9 年前

    理论上,是的:数据写入需要验证约束。

    在实践中,很少这样做:除非经过衡量和证明,否则您可以假设没有性能影响。绝大多数情况下,性能问题是由其他问题引起的:

    • 错误的架构设计(缺少索引,错误的聚集索引选择)
    • 争用(阻塞),同样由于错误的模式设计(表扫描保证锁冲突)
    • 错误的查询设计

    在设计良好的模式和良好的查询中,约束成本将开始显示在 非常 高吞吐量。当这种情况发生时,有预防措施。

    我的2C: 从未 为一些难以实现的性能目标牺牲正确性约束。在非常罕见的情况下,当约束确实是问题的时候,会有度量来证明这一点,正如俗话所说:如果你不得不问它的成本是多少,你就买不起它。如果你不得不问约束是否是一个问题,你就不能删除它们(无意冒犯)。

        4
  •  4
  •   Jim Mitchener    15 年前

    对于插入/更新/删除,简短的回答是“是”。数据库需要检查引用完整性是否完整,是否允许创建/修改。或者在delete的情况下,可能需要执行一些级联操作。

    对于selects,事实上恰恰相反。外键还有一个额外的秘密好处,它可以精确地显示您最可能进行复杂连接的位置,并且具有非常常用的字段。这使得索引工作更加容易,而且您可以非常保证所有FK字段都应该被索引。这使得选择 许多的 更快。

        5
  •  4
  •   HLGEM    15 年前

    外键可能会导致子表中的插入(或某些更新)或父表中的删除花费更长的时间。不过,这是一件好事,因为这意味着要确保数据的完整性。除非您不想拥有有用的数据,否则没有理由跳过使用外键。通常情况下,除非有许多外键与同一父表相关,或者在一个批中插入或删除多个记录,否则您不会注意到有太大的差异。此外,我注意到,用户在插入或删除中比在选择中更能容忍额外的几秒钟。用户也不能容忍所有不可靠的数据,这些数据是您没有外键约束的数据。

    您需要对它们进行索引,以提高选择查询的性能。

        6
  •  3
  •   Fritz    12 年前

    外键检查比大多数人想象的要花更多的时间。当前使用Oracle11g和一个带有两个外键的表进行的测试表明,使用启用的外键插入大约800000行的时间为60秒,但不使用外键只需20秒。 (当然,外键列已编入索引)

    总之,我同意所有其他海报的观点,即完整性约束不是一个选项,而是保持数据一致性的唯一方法。但是,对于导入,尤其是空表中的导入,如果时间很关键,则可以选择在导入时禁用外键。

        7
  •  2
  •   Dave Swersky    15 年前

    如果外键以这种方式有任何影响,那么它将影响插入。数据库在创建/修改记录(而不是选择记录)时对外键执行参照检查。

        8
  •  2
  •   blispr    15 年前

    在大多数情况下,外键不会影响查询性能,强烈建议使用外键。通过帮助规范化,您将消除冗余数据,如果您通过添加基础索引(针对适当的外键)进行后续操作,您将获得良好的查询性能。

    外键可以帮助查询优化器获得给定查询的最佳查询计划。

    当您更新数据时,外键检查是一个因素(这是一个单独的考虑因素——我假设这里您关心的是查询——除非您用“查询”这个词来表示这两者)。

        9
  •  0
  •   jaywon    15 年前

    我相信这篇文章指出,在FK字段上添加一个索引可以提高性能,而不仅仅是FK关系提高了性能。表上存在FK不应对select查询有任何影响,除非正在执行联接操作,此时,FK字段上的FK关系和索引将提高性能。

        10
  •  0
  •   Pete    15 年前

    如果您强制执行引用完整性,那么影响FK字段的插入和更新将变慢。但是,通常不需要担心太多,特别是因为许多DBS都是80%读/20%写。这也是值得付出的代价。

    在一个外键上创建一个索引通常是有益的,尽管很明显,它在多大程度上取决于您正在运行的select语句。

    一般来说,由于正常化(避免重复数据和同步问题),您需要外键。正常化到3度,然后在分析现实世界的性能后,可以考虑去正常化。

        11
  •  0
  •   Nate Watson    9 年前

    外键会减慢插入和更改的速度,因为必须验证每个外键引用。根据DBMS是否使用外键索引,外键既不能影响选择,也可以使选择更快。

    外键对删除有复杂的影响。如果要删除引用外键的内容,它不会影响任何内容,但如果要删除的内容被另一行/表中的外键引用,则通常会导致问题。

    外键可能会导致表创建和更改中的性能略有下降。

    当然,这都假定使用了外键验证。