2008-12-17 167 views
6

我的工作在别人的PHP代码,并在看到这个模式和过:LEFT JOIN与多个SELECT语句

(伪)

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可以做到这一点吗?我错过了一些性能优势?可移植性问题?或者我只是挑剔?

+0

自1987年以来,我一直在使用SQL数据库,但我从未接受过任何SQL课程。直到最近,我可能会以第一种方式做到这一点,因为我不了解LEFT JOIN。 – 2008-12-17 23:21:02

+0

这个_really_需要九个以上的答案吗? – Will 2008-12-17 23:29:30

+2

@会,你有什么反对每个人把他们的帽子扔进答案环吗?更好的答案越好,好的答案就会浮出水面。 – mmcdole 2008-12-18 01:38:21

回答

5

没有足够的信息来真正回答问题。由于某种原因,我减少查询计数并增加查询计数的原因是由于另一个原因这两个都改善了性能。在同一个应用程序!

对于表的大小,数据库配置和频率的外部表将被查询的某些组合,做两个查询可以更快比LEFT JOIN。 但经验和测试是唯一会告诉你,。具有中等大表的MySQL似乎对此感到不可思议,IME。在一张桌子上执行三个查询通常比一个查询加入三个查询快得多。我已经看到了一个数量级的加速。

3

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

2

有治疗你的SQL数据库管理系统,如果它是一个ISAM文件系统,在同一时间从一个单一的表中选择的危险。在外连接中使用单个SELECT可能会更清晰。另一方面,在应用程序代码中检测到null并根据null与non-null决定做什么也不是完全干净的。

单个语句的一个优点 - 您有更少的往返服务器 - 特别是如果每​​次需要其他结果时都动态准备SQL。

平均而言,单个SELECT语句更好。它为优化器提供了一些东西,并将其保存得过于无聊。

+0

是的,我们必须保持优化者的满意度! :-) – 2008-12-17 23:33:36

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; 

这样你就可以检查你是否得到了一个结果,并让数据库在一个查询中完成所有繁重的工作,而不是两个...

是的,我认为看起来好像你所说的是正确。

6

这是绝对错误的。你没有理由再次通过电线。数据库在他们的问题空间非常快。连接表就是其中之一,你会看到更多的性能从第二个查询,然后是联接。除非你的表空间有成千上万的记录,否则这不是一个好主意。

1

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

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

1

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

我现在有两个或三个实例,其中原来的查询是我继承的,它由一个查询组成,这个查询有很多连接,并且需要SQL准备好语句。

我回到了程序,利用一些表变量(或临时表),并打破了查询分解成很多小单选择类型语句和构造的最终结果以这种方式设置。

此更新显着地将响应时间固定为几秒,因为更容易执行大量简单的“一次性”检索必要的数据。

我并不想在这里为对象着想的反对,而只是指出该代码可能已经被分解到这样的粒度级别来解决类似的问题。

2

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

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

避免的神话联接好像是说我们应该避免在应用程序代码的编写循环,因为运行的代码行多次明显高于一次运行更慢。不要在每次迭代期间对++i的“开销”和测试i<20

1

单个SQL查询将更多的表现为SQL服务器(有时不共享相同的位置),导致只需要处理一个请求,如果你想使用多个SQL查询,然后您介绍了很多的开销:

执行更多的CPU指令, 发送第二查询到服务器, 在服务器上创建第二个线程, 对服务器执行的可能更多的CPU指令 ,破坏服务器上的第二个线程 ,发第二次结果 回来。

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

1

做一个简单的两个表连接通常是解决这个问题域的最好方法,但是根据表和索引的状态,在某些情况下可能会更好地执行两个select语句,但通常我还没有碰到这个问题,直到我开始接近3-5连接的表,不只是2

只要确保你已经覆盖两个表的索引,以确保不会扫描磁盘的所有记录,这是最大的性能打了一个数据库中获取(在我有限的经验)

2

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

这个概念背后的关键思想是,编译器/查询优化可以做一个更好的工作,如果他们知道整个问题域,而不是它的一半。

1

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

1

有很多情况下,这将需要不同的解决方案,这是不可能的解释都在一起。

加入扫描两个表,并循环到匹配第二个表中的第一个表的记录。在许多情况下,简单选择查询的运行速度会更快,因为它仅关注主键/唯一键(如果存在)以在内部搜索数据。