使用JOIN或使用EXISTS可以获得更好的性能吗?

时间:2008-10-22 18:36:27

标签: sql performance

我有两个表机构和结果,我想看看机构是否有任何结果我可以排除那些没有结果的结果。

使用JOIN或使用EXISTS可以获得更好的性能吗?

谢谢你,
-Nimesh

12 个答案:

答案 0 :(得分:18)

根据语句,统计信息和数据库服务器,它可能没有区别 - 可能会生成相同的优化查询计划。

基本上有三种方式可以将DB连接到桌面下面:

  • 嵌套循环 - 一个比第二个大得多的表。检查较小表中的每一行是否有较大的每一行。

  • 合并 - 对于同一排序顺序的两个表。两者都按顺序运行并匹配它们对应的位置。

  • 哈希 - 其他一切。临时表用于建立匹配。

通过使用exists,您可以有效地强制查询计划执行嵌套循环。这可能是最快捷的方式,但实际上您需要查询计划程序来决定。

我想说你需要编写两个SQL语句并比较查询计划。根据您拥有的数据,您可能会发现它们的变化很大。

例如,如果[INSTIT]和[Results]的大小相似,并且两者都集中在InstitutionID上,那么合并连接将是最快的。如果[Results]比[INSTIT]大得多,嵌套循环可能会更快。

答案 1 :(得分:14)

取决于。

最终,2服务完全不同。

您加入2个表来访问相关记录。如果您不需要访问相关记录中的数据,则无需加入它们。

EXISTS可用于确定令牌是否存在于给定数据集中,但不允许您访问相关记录。

发布您想到的两种方法的示例,我可能会给您一个更好的主意。


使用您的两个表机构和结果如果您想要一个有结果的机构列表,这个查询将是最有效的:

select Institutions.institution_name 
from Institutions
inner join Results on (Institutions.institution_id = Results.institution_id)

如果您有institution_id并且只想知道它是否有结果,那么使用EXISTS可能会更快:

if exists(select 1 from Results where institution_id = 2)
  print "institution_id 2 has results"
else
  print "institution_id 2 does not have results"

答案 2 :(得分:5)

这取决于你的优化器。我在Oracle 10g和11g中尝试了以下两个。在10克,第二个稍快。在11克,他们是相同的。

然而,#1实际上是对EXISTS条款的滥用。使用联接查找匹配项。

select *
from
  table_one t1
where exists (
             select *
             from table_two t2
             where t2.id_field = t1.id_field
             )
order by t1.id_field desc


select t1.*
from 
  table_one t1
 ,table_two t2
where t1.id_field = t2.id_field
order by t1.id_field desc 

答案 3 :(得分:4)

无论是否存在性能差异,您都需要使用更适合您的目的。您的目的是获取机构列表(不是结果 - 您不需要额外的数据)。因此,选择没有结果的机构......翻译 - 使用EXISTS。

答案 4 :(得分:3)

我说JOIN速度较慢,因为一旦EXISTS调用找到了某些内容,查询就会停止,而JOIN会一直持续到最后。

编辑:但这取决于查询。这应该根据具体情况来判断。

答案 5 :(得分:1)

您是否将EXISTS用作相关子查询的一部分?如果是这样,连接几乎总是更快。

您的数据库应该有基准查询的方法。使用它们来查看哪个查询运行得更快。

答案 6 :(得分:1)

实际上,根据您对问题的模糊描述,听起来像NOT IN查询是最明显的编码方式:

SELECT *
  FROM Institutions
  WHERE InstitutionID NOT IN (
     SELECT DISTINCT InstitutionID
       FROM Results
     )

答案 7 :(得分:1)

LEFT OUTER JOIN往往比NOT EXISTS **表现更好,但在你的情况下你想要做EXISTS并且使用简单的INNER JOIN并不能完全复制EXISTS行为。如果您有多个机构的结果,则执行INNER JOIN将为该机构返回多行。你可以通过使用DISTINCT解决这个问题,但是无论如何EXISTS可能会更好地表现。

**对于那些不熟悉这种方法的人:

SELECT
     MyTable.MyTableID
FROM
     dbo.MyTable T1
LEFT OUTER JOIN dbo.MyOtherTable T2 ON
     T2.MyTableID = T1.MyTableID
WHERE
     T2.MyOtherTableID IS NULL

相当于

SELECT
     MyTable.MyTableID
FROM
     dbo.MyTable T1
WHERE NOT EXISTS (SELECT * FROM MyOtherTable T2 WHERE T2.MyTableID = T1.MyTableID)

假设MyOtherTableID是NOT NULL列。第一种方法通常比NOT EXISTS方法执行得更快。

答案 8 :(得分:1)

如果RESULTS表每INSTITUTION行有多行,EXISTS()的好处是不要求您选择不同的机构。

至于性能,我看到joins, IN(), and EXISTS()在各种用途中都是最快的。要找到最适合您的方法,您必须进行测试。

答案 9 :(得分:1)

在上述情况下,Exists语句的工作速度比连接速度快。 存在将为您提供单一记录,也将节省时间。 在连接的情况下,记录的数量将更多,并且必须使用所有记录。

答案 10 :(得分:0)

如果您指的是使用左(或右)外连接或不存在子查询,我相当肯定左外连接在性能方面胜出。例如:

SELECT t1.* FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.id = t2.id WHERE t2.id IS NULL

上面应该比等效的子查询更快,如果你专门提到存在 - 那么,在结构允许的情况下,内连接将始终是首选选项。

答案 11 :(得分:0)

如果你想要那些没有结果的机构,那么'Where Not Exists'子查询会更快,因为一旦找到有结果的那个结果,它就会停止...

如果你想要机构有结果,但你实际上并不想要结果,同样的事情。使用“Where Exists”子查询..它会在找到单个结果后立即停止...这也可以确保结果集每个机构只有一个记录,而如果您有一个具有多个结果的机构,则使用加入方法需要您添加'distinct'关键字或'Group By'子句,以消除将从与单个机构匹配的多个Result记录中产生的重复cartesion产品行。

如果您需要结果,那么如果您不想看到没有结果的机构,请进行加入 - 内部加入;如果您想要查看所有机构,包括没有结果的机构,则进行外部联接。