代码之家  ›  专栏  ›  技术社区  ›  Midhat

避免嵌套查询

  •  16
  • Midhat  · 技术社区  · 15 年前

    避免嵌套查询有多重要。

    我总是学会像躲避瘟疫一样躲避它们。但它们对我来说是最自然的。在设计查询时,我首先编写的是嵌套查询。然后我将其转换为joins,这有时需要很长时间才能纠正。很少有大的性能提升(有时的确如此)

    他们真的很坏吗?有没有办法使用不带临时表和文件排序的嵌套查询

    3 回复  |  直到 6 年前
        1
  •  7
  •   Unreason    15 年前

    这确实取决于,我曾经使用子查询改进过一些查询。

    我知道的因素有:

    • 子查询是否使用外部查询中的字段进行比较( correlated 是否)
    • 如果外部查询和子查询之间的关系由索引覆盖
    • 如果联接上没有可用的索引,并且子查询不相关并返回一个小结果,则使用它可能会更快
    • 我也遇到过这样的情况:将使用order by的查询转换为不使用它的查询,并将其转换为一个简单的子查询和排序,从而提高mysql的性能

    无论如何,测试不同的变体(请使用SQL无缓存)总是很好的,将相关查询转换为连接是一个很好的实践。

    我甚至认为这是一种非常有用的做法。

    如果您首先想到的是相关查询,那么您可能不会主要考虑集合操作,而是主要考虑过程操作,在处理关系数据库时,在数据模型及其转换。

    编辑: 程序与关系
    在某些集合代数表达式中,从集合运算和过程的角度来思考问题可以归结为等价性,例如,在并集上的选择等价于选择的并集。两者没有区别。
    但是,当您比较这两个过程时,例如将选择条件应用于具有make a union的union的每个元素,然后应用选择,这两个过程是截然不同的,它们可能具有非常不同的属性(例如cpu、i/o、内存的利用率)。

    关系数据库背后的思想是,您不试图描述如何获得结果(过程),而只描述您想要的结果,并且数据库管理系统将决定满足您的请求的最佳路径(过程)。这就是为什么调用sql 4th generation language (4GL) .

    帮助您做到这一点的技巧之一是提醒您自己元组没有内在的顺序(set元素是无序的)。 另一个是认识到关系代数是非常全面的,它允许将请求(需求)直接转换为sql(如果模型的语义很好地表示了问题空间,或者换言之,如果表和关系的名称所附加的含义是正确的,或者换句话说,如果你的数据库设计得很好的话)。

    所以,你不用想怎么做,只要想什么。

    在您的例子中,这只是对相关查询的偏好,所以可能是我没有告诉您任何新的内容,但是您强调了这一点,因此给出了注释。

    我认为如果您完全熟悉将查询从一种形式转换为另一种形式的所有规则( rules 例如分布性)您不喜欢相关的子查询(您将看到所有形式都是相等的)。

    (注意:上面讨论了理论背景,这对数据库设计很重要;实际上,上述概念有所偏离-并非所有查询的等效重写都必须执行得一样快,集群主键确实会使表在磁盘上具有继承顺序,等等…)但这些偏差仅仅是偏差;并非所有等价查询都能以如此快的速度执行,这是实际DBMS的缺陷,而不是其背后的概念)

        2
  •  1
  •   Community CDub    8 年前

    我不确定它在mysql 5.1或5.5中是什么样子,但是在5.0.x中嵌套查询通常有糟糕的性能,因为mysql对从主查询获取的每一行执行子查询。 对于更成熟的数据库(如mssql)来说,情况可能并非如此,后者在内部可以将嵌套查询重写为联接,但我从未使用过mssql,所以我不确定。

    http://dev.mysql.com/doc/refman/5.0/en/rewriting-subqueries.html

    在某些情况下,不仅可以在不使用子查询的情况下重写查询,而且可以更有效地使用其中的一些技术,而不是使用子查询。 -考虑到目前为止对我来说 全部的 子查询使数据库爬网。

    Subqueries vs joins

        3
  •  0
  •   Anto    6 年前

    就我个人而言,我更喜欢避免嵌套查询,直到它们是必要的,原因很简单,嵌套查询会降低代码的可读性,使调试和协作更加痛苦。我认为,如果嵌套查询很简单,或者大表的临时存储成为一个问题,那么嵌套是可以接受的。但是,我在嵌套查询中多次看到复杂的嵌套查询,这使调试非常痛苦。