Sql 使用联接或使用EXISTS可以获得更好的性能吗?

Sql 使用联接或使用EXISTS可以获得更好的性能吗?,sql,performance,Sql,Performance,我有两个表格机构和结果,我想看看机构是否有任何结果,这样我就可以排除那些没有结果的 使用联接或使用EXISTS可以获得更好的性能吗 谢谢你, -Nimesh如果您指的是使用左(或右)外部联接或不存在子查询,那么我相当肯定左外部联接在性能方面会获胜。例如: 从表1中选择t1.*t1.id=t2.id上的t1左外连接表2 t2,其中t2.id为空 上面的查询应该比等价的子查询要快,如果您专门指的是exists,那么在结构允许的情况下,内部连接将始终是首选选项。这取决于具体情况 最终,这两种服务的目

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

使用联接或使用EXISTS可以获得更好的性能吗

谢谢你,

-Nimesh

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

从表1中选择t1.*t1.id=t2.id上的t1左外连接表2 t2,其中t2.id为空

上面的查询应该比等价的子查询要快,如果您专门指的是exists,那么在结构允许的情况下,内部连接将始终是首选选项。

这取决于具体情况

最终,这两种服务的目的完全不同

您可以联接两个表以访问相关记录。如果不需要访问相关记录中的数据,则无需加入它们

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

张贴一个你心目中的两种方法的例子,我可能会给你一个更好的想法


使用两个表Institutions and Results如果您想要有结果的机构列表,此查询将是最有效的:

select Institutions.institution_name 
from Institutions
inner join Results on (Institutions.institution_id = Results.institution_id)
如果您有一个机构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"

我认为连接速度较慢,因为一旦EXISTS调用找到某个内容,查询执行就会停止,而连接将一直持续到最后


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

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


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

无论是否存在性能差异,您都需要使用更适合您的查询。你的目的是得到一份机构列表(不是结果——你不需要额外的数据)。所以选择没有结果的机构。。。翻译-存在使用。

如果您想要没有结果的机构,那么“Where not EXISTS”子查询会更快,因为它会在为有结果的机构找到单个结果时立即停止


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


如果你需要结果,那么做一个连接——如果你不想看到没有结果的机构,那么做一个内部连接;如果你想看到所有机构,包括没有结果的机构,那么做一个外部连接

这取决于您的优化器。我在Oracle 10g和11g中尝试了以下两种。在10g中,第二个稍微快一点。在11g中,它们是相同的

然而,#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 

根据语句、统计信息和数据库服务器的不同,它可能不会有什么不同-可能会生成相同的优化查询计划

DBs在后台连接表的基本方式有三种:

  • 嵌套循环-一个表比第二个表大得多。较小表格中的每一行都会针对较大表格中的每一行进行检查

  • 合并-用于排序顺序相同的两个表。两者都按顺序排列,并在相应的位置匹配

  • 散列-其他所有内容。临时表用于建立匹配项

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

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


例如,如果[Institutions]和[Results]的大小相似,并且都聚集在InstitutionID上,则合并联接将是最快的。如果[Results]比[Institutions]大得多,嵌套循环可能会更快。

实际上,从您对问题的模糊描述来看,在我看来,不在查询是编码它的最明显方式:

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

左外部连接的性能往往比不存在的连接好**,但在您的情况下,您希望执行存在的操作,而使用简单的内部连接并不能完全复制存在的行为。如果一个机构有多个结果,则执行内部联接将返回该机构的多行。您可以通过使用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是非空列。但是,第一种方法的执行速度通常比不存在的方法快。

如果结果表中每个
机构有多行
存在()
还有一个额外的好处,即不需要您选择不同的机构


至于性能,我已经看到
连接、IN()和EXISTS()在各种用途中都是最快的。为了找到适合您的目的的最佳方法,您必须进行测试。

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

这不是一个真正的问题,因为