LEFT JOIN与多个SELECT语句

时间:2008-12-17 23:02:16

标签: sql

我正在研究其他人的PHP代码并一遍又一遍地看到这种模式:

(伪代码)

result = SELECT blah1, blah2, foreign_key FROM foo WHERE key=bar

if foreign_key > 0  
  other_result = SELECT something FROM foo2 WHERE key=foreign_key  
end

如果另一个表中没有相关的行,代码需要分支,但是通过在单个SELECT语句中执行LEFT JOIN不能更好地完成此操作吗?我错过了一些性能优势吗?便携性问题?或者我只是在挑剔?

13 个答案:

答案 0 :(得分:6)

这绝对是错误的。你无缘无故地第二次越过电线。数据库在他们的问题空间非常快。连接表就是其中之一,你会看到更多的性能从第二个查询到连接的性能下降。除非你的表空间是数以亿计的记录,否则这不是一个好主意。

答案 1 :(得分:5)

没有足够的信息来真正回答这个问题。我一直致力于减少查询计数的应用程序,原因之一是由于另一个原因而增加查询次数两者都提高了性能。在同一个应用程序中!

对于表大小,数据库配置以及查询外表的频率的某些组合,执行这两个查询可能比LEFT JOIN快得多。 但经验和测试是唯一可以告诉你的事情。具有中等大小表的MySQL似乎对此很容易接受,IME。在一个表上执行三个查询通常比一个查询加入三个查询要快得多。我已经看到了一个数量级的加速比。

答案 2 :(得分:3)

我和你在一起 - 单个SQL会更好

答案 3 :(得分:2)

将SQL DBMS视为ISAM文件系统存在危险,一次只能从一个表中进行选择。将单个SELECT与外部联接一起使用可能更清晰。另一方面,在应用程序代码中检测null并根据null与非null决定做什么也不是完全干净。

单个语句的一个优点 - 您可以减少到服务器的往返次数 - 尤其是每次需要其他结果时动态准备SQL。

平均而言,单个SELECT语句更好。它为优化器提供了一些可以做的事情,并且保存得太闷了。

答案 4 :(得分:2)

在我看来,你所说的内容是相当有效的 - 为什么在一个人做的时候会发出两次对数据库的调用 - 除非两个记录都是作为对象独立需要的(?)

当然,虽然在数据库的一次调用中将它全部拉回来并将字段分成两个单独的对象可能不是那么简单的代码,但它确实意味着你只依赖于数据库打电话而不是两个......

这可以更好地作为查询阅读:

Select a.blah1, a.blah2, b.something From foo a Left Join foo2 b On a.foreign_key = b.key Where a.Key = bar;

通过这种方式,您可以检查您是否一次性获得了结果并让数据库在一个查询中完成所有繁重的工作,而不是两个......

是的,我认为你所说的似乎是正确的。

答案 5 :(得分:2)

最可能的解释是开发人员根本不知道外连接是如何工作的。这种情况非常普遍,即使是在自己专业方面经验丰富的开发人员也是如此。

还有一个普遍的说法是“加入查询的速度很慢”。因此,许多开发人员不惜一切代价盲目地避免加入,即使是在运行多个查询的情况下也会更好。

避免连接的神话就像说我们应该避免在应用程序代码中编写循环,因为多次运行一行代码显然比运行一次要慢。更不用说++i的“开销”并在每次迭代中测试i<20

答案 6 :(得分:2)

完全正确的是单一查询是要走的路。为了给其他答案添加一些价值,让我添加这个公理:“使用正确的工具完成工作,数据库服务器应该处理查询工作,代码应该处理程序工作。”

这个概念背后的关键思想是,如果编译器/查询优化器知道整个问题域而不是其中的一半,那么编译器/查询优化器可以做得更好。

答案 7 :(得分:1)

考虑到在一个数据库中,您拥有所需的所有数据,只需一个SQL语句就可以在99%的时间内获得更好的性能。在这种情况下不确定连接是否正在动态创建,但如果这样做则很昂贵。即使重用现有连接的过程,DBMS也没有优化查询,这是最好的方式,而不是真正利用这些关系。

出于性能原因,我能看到这样的调用的唯一方法是,外键检索的数据量很大而且在某些情况下只需要它。但是在你描述的样本中它只是抓住它,如果它存在,所以情况并非如此,因此没有获得任何性能。

答案 8 :(得分:1)

所有这一切的唯一“问题”是,如果要使用的结果集包含大量连接,甚至是嵌套连接。

我现在有两个或三个实例,我继承的原始查询由一个查询组成,其中有很多连接,并且SQL需要花费很长时间来准备语句。

我回到过程中,利用了一些表变量(或临时表),并将查询分解为许多较小的单一选择类型语句,并以这种方式构造最终结果集。

这个更新大大地将响应时间缩短了几秒钟,因为更容易做很多简单的“一次性”来检索必要的数据。

我不是要在此反对反对意见,而只是指出代码可能已被细分到如此精细的级别以解决类似的问题。

答案 9 :(得分:1)

单个SQL查询会带来更高的性能,因为SQL服务器(有时不共享相同的位置)只需要处理一个请求,如果您使用多个SQL查询,那么您会引入大量开销:< / p>

  

执行更多CPU指令,   向服务器发送第二个查询,   在服务器上创建第二个线程,   执行更多的CPU指令   在服务器上,销毁第二个线程   在服务器上,发送第二个结果   回来。

可能会出现性能可能更好的特殊情况,但对于简单的事情,您可以通过多做一些工作来达到更好的性能。

答案 10 :(得分:1)

执行简单的两个表连接通常是解决此问题域的最佳方法,但是根据表的状态和索引,在某些情况下,执行两个select语句可能更好,但通常在我开始接近3-5个连接表之前,我没有遇到过这个问题,而不仅仅是2个。

请确保您在两个表上都有覆盖索引,以确保您没有扫描磁盘上的所有记录,这是数据库获得的最大性能损失(在我有限的经验中)

答案 11 :(得分:1)

您应始终尽量减少对数据库的查询次数。您的示例仅适用于1个查询。这样您以后可以更容易地缓存或同时处理更多请求,因为不是总是使用需要连接的2-3查询,而是每次只有1个。

答案 12 :(得分:1)

有许多案例需要不同的解决方案,而且无法一起解释。

Join扫描表和循环以匹配第二个表中的第一个表记录。在许多情况下,简单选择查询将更快地工作,因为它只关注主/唯一密钥(如果存在)以在内部搜索数据。