避免嵌套查询

时间:2010-05-06 06:02:39

标签: sql mysql sql-server

避免嵌套查询的重要性。

我一直学会像瘟疫一样避免它们。但它们对我来说是最自然的事情。当我设计查询时,我写的第一件事是嵌套查询。然后我将它转换为连接,这有时需要很长时间才能正确。并且很少会带来很大的性能提升(有时确实如此)

他们真的很糟糕。有没有办法使用没有临时表和filesort的嵌套查询

3 个答案:

答案 0 :(得分:7)

这实际上取决于我在某些情况下使用子查询改进了一些查询。

我所知道的因素是:

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

无论如何,测试不同的变体(请使用SQL_NO_CACHE)总是好的,并且将相关查询转换为连接是一种很好的做法。

我甚至会把它称为一种非常有用的做法。

如果相关的查询首先出现在您的脑海中,您可能不是主要考虑集合操作,而主要是在过程操作方面以及在处理关系数据库时,它是完全非常有用的采用数据模型的集合视角和变换。

编辑: 程序与关系
在集合运算与程序方面的思考归结为某些集合代数表达式中的等价性,例如对于并集的选择等同于选择的并集。两者没有区别 但是当你比较两个过程时,例如将选择标准应用于联合的每个元素并生成联合然后应用选择,这两个是明显不同的过程,这些过程可能具有非常不同的属性(例如CPU的利用率,I / O,记忆)。

关系数据库背后的想法是,您不会尝试描述如何获得结果(过程),而只是描述您想要的,并且数据库管理系统将决定满足您的请求的最佳路径(过程) 。这就是SQL被称为4th generation language (4GL)的原因。

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

因此,您不必考虑如何,只考虑是什么。

在你的情况下,它只是偏好相关的查询,所以可能是我没有告诉你任何新的东西,但你强调了这一点,因此评论。

我认为,如果您完全熟悉将查询从一种形式转换为另一种形式(rules,例如分配性)的所有规则,那么您就不喜欢相关的子查询(您会看到所有形式相同)

(注意:上面讨论了理论背景,对于数据库设计很重要;实际上上面的概念有所不同 - 并非所有等同的查询重写都必须以快速执行,集群主键确实使表在磁盘上具有继承顺序等。但是这些偏差只是偏差;并非所有等效查询执行速度都快,这是实际DBMS的不完美而不是其背后的概念)

答案 1 :(得分:1)

我不确定它在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

答案 2 :(得分:0)

我个人更喜欢避免使用嵌套查询,直到它们成为必需,原因很简单,因为嵌套查询会使代码的可读性降低,并使调试和协作更加痛苦。我认为,如果嵌套查询比较琐碎,或者大表的临时存储成为问题,则嵌套是可以接受的。但是太多次我已经看到嵌套查询中复杂的嵌套查询,这使调试变得很痛苦。

相关问题