在与朋友的讨论中,我听到了两件事 -
使用约束会导致性能略有下降。例如。考虑唯一性约束。在插入之前,DBMS必须检查所有现有数据的唯一性,从而导致额外的计算。
他建议确保在应用程序级逻辑本身处理这些约束。例如。正确地从两个表中删除行,而不是放置外部完整性约束等。
第一个对我来说听起来有点合乎逻辑,但第二个看起来很直观。我没有足够的DBMS经验来真正判断这些说法。
Q值。索赔1是否正确?如果是这样,那么权利要求2甚至是处理这种情况的正确方法吗?
答案 0 :(得分:6)
如果您的数据需要正确,您需要强制执行约束,如果您需要强制执行约束,让数据库为您执行此操作将比其他任何事情更快(并且可能更正确)。
尝试在应用程序级别强制执行类似键唯一性的操作可以正确或快速完成,但不能同时执行。例如,假设您要插入新行。一个天真的应用程序级算法可能看起来像这样:
这实际上可以在单客户端/单线程环境中运行。但是,在并发环境中,其他一些客户端可以在您的步骤1和步骤2之间编写相同的键值,并且presto:您自己在数据中没有重复,甚至不知道它!
要防止出现竞争条件,您必须使用某种形式的锁定,并且由于您要插入 new 行,因此没有行锁定 - 你可能最终会锁定整个表格,从而破坏了整个过程中的可扩展性。
OTOH,如果你让DBMS为你做这件事,它可以在没有太多锁定的情况下以特殊的方式完成它,已经过测试并在所有棘手的并发边缘情况下进行了双重测试,并且其性能有在DBMS进入市场的过程中进行了优化。foreign keys同样存在问题。
所以,是的,如果您的应用程序是唯一一个访问数据库的应用程序(例如,当使用嵌入式数据库时),您可能会逃避应用程序级实施,但是如果DBMS可以为您做到这一点,为什么会这样做呢?
但是在并发环境中,将密钥和外键保留在数据库中 - 无论如何,您还要做很多工作,强制执行您的自定义"业务逻辑" (这不是直接"在DBMS中声明"以正确和高效的方式...
话虽如此,随意执行任何应用程序级别"预检查"这有利于您的用户体验。但是另外对数据库级约束,而不是它们。
答案 1 :(得分:2)
权利要求1是正确的,权利要求2是不正确的,就像你的结论一样。
数据库的工作是处理数据及其完整性。应用程序的工作是向数据库询问有关数据的信息,然后使用数据执行工作。
如果您通过应用程序处理#2:
你必须处理并发 - 当有超过1个连接活动到数据库时会发生什么?您需要锁定表以执行操作以确保唯一性或完整性。由于此连接可能随时中断,因此您手上有一个很大的问题。当锁定它的进程死亡时如何解锁表?
您无法通过应用程序比数据库本身做得更好。您仍然需要检查行的唯一性,这意味着您需要检索所有数据,对整个数据集执行检查然后编写它。你不能比数据库更好或更快地做任何事情 - 根据定义,它会更慢,因为你需要将数据从数据库传输到你的应用程序
数据库是在考虑并发性的情况下制作的。使用朋友的逻辑创建优化是导致不稳定的应用程序,重复数据,无响应的数据库等的原因。从不这样做。让数据库完成它的工作,它就是出于这样的目的。
在检查唯一性时,MySQL使用索引作为快速访问的数据结构。与任何应用程序可以做的相比,MySQL执行唯一性检查的速度是无与伦比的 - 它只是更快地完成工作。如果您需要唯一数据,则需要确保拥有唯一数据 - 这是一个无法避免的工作负载,而开发数据库的人员则使用经过验证的速度算法。它已经以最佳速度工作。
至于完整性 - 同样,MySQL(或任何其他RDBMS)用于处理此类场景。如果在app逻辑中实现外键约束会更好,那么我们首先不会有FK可用。就像我之前提到的那样 - 数据库的工作就是照顾它。
关系数据库的ACID没有任何理由。原子性,一致性,隔离性,耐用性MySQL的InnoDB实现并允许这些,如果您需要它 - 然后您使用它。与MySQL的内部处理方式相比,任何人都无法创建任何能够以任何方式表现更好的语言的应用程序。
TL; DR:你的想法是正确的。
答案 2 :(得分:2)
是的,检查约束确实需要花费时间并减慢数据库更新。
但是,如果将这种逻辑转移到应用程序将导致净性能提升,这一点都不清楚。现在,您至少有两次单独的数据库访问:一次检查约束,另一次检查以执行更新。数据库的每次访问都需要花费时间:建立连接需要时间,数据库引擎需要时间来解析查询并构建查询计划,返回结果需要时间。由于数据库引擎不知道您正在做什么或为什么,它无法优化。在实践中,一次“大访问”几乎总是比完成同样事情的两次“小访问”便宜。
我这里主要讲的是唯一性约束和关系完整性约束。如果您有一个可以在不访问数据库的情况下进行测试的约束,例如单个字段的范围限制,那么在应用程序中执行此操作会更快。由于各种原因,可能仍然不是一个好主意,但它会更快。
答案 3 :(得分:1)
约束通常会导致轻微性能下降。没有什么是免费的。但是,有两个重要的考虑因素:
当然也有例外,但大多数数据库的查询次数要多于修改后的查询次数。因此,如果您可以将性能命中从查询转移到DML,通常可以加快系统的整体性能。
一定要在应用级别执行单独的约束检查。在收集数据的过程中向用户提供反馈是非常有益的("交付日期不能过去!")而不是等到将数据插入数据库的尝试失败。
但这并不意味着将它们从数据库中删除。这种冗余非常重要。您能绝对保证在数据库上执行的唯一操作将来自应用程序吗?绝对不。在应用程序外部进行的正常维护活动太多,无法做出承诺。更不用说通常有多个应用程序,因此保证必须适用于每个应用程序。太多松散的结局。
在设计数据库时,数据完整性是您的首要任务。永远不要为了性能而牺牲它,特别是因为精心设计的数据库的性能通常不是问题,即使是这样,也有很多方法可以提高性能,而不涉及消除约束(或非规范化,另一个错误许多人仍在努力提高OLTP系统的性能。)
答案 4 :(得分:0)
问:问。索赔1是否正确?
是的。以我的经验,使用约束会导致性能大幅下降。 性能影响与表中的约束和记录的数量有关。随着表记录的增长,性能会受到影响,并且数据库性能可能会很快从坏变为坏。
例如。在我工作的一家审计公司中,过程的一部分是将包含大量职责/角色/职能的excel矩阵序列化为具有许多FK约束的一组表。 最初的性能不错,但是在6个月到一年的时间内,此序列化过程花费了几分钟。我们尽了最大的努力优化了影响。如果我们关闭约束,那么此过程将在几秒钟内完成。
如果是这样(如果权利要求1是正确的话),权利要求2甚至是处理此类情况的正确方法吗?
是的,但在某些情况下。
因此,由于我们在审计公司遇到的性能问题,我们着眼于将约束检查移至应用程序数据集中。因此,从本质上讲,数据集用于检查和验证约束,矩阵DB表仅用于存储(和处理)。
注意:这对我们有用,因为矩阵数据一旦插入就永远不会改变,并且每个矩阵都独立于过去插入的所有其他矩阵。