避免嵌套查询

Mid*_*hat 18 mysql sql sql-server

避免嵌套查询有多重要.

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

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

Unr*_*son 8

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

我所知道的因素是:

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

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

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

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

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

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

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

因此,你不必考虑如何,只有什么.

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

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

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