左外连接上的SQL性能与不存在

如果我想在表A中find一组条目,但不能在表B中find,我可以使用LEFT OUTER JOIN或NOT EXISTS。 我听说SQL Server面向ANSI,在某些情况下,LEFT OUTER JOIN比NOT EXISTS更有效率。 在这种情况下,ANSI JOIN会执行得更好吗? 在SQL Server上,连接运算符比NOT EXISTS更有效吗?

乔的联系是一个很好的起点。 Quassnoi也涵盖了这一点。

一般来说,如果你的字段被正确地编入索引,或者如果你期望过滤掉更多的logging(即在子查询中有很多行EXIST ), NOT EXISTS将会performance更好。

EXISTSNOT EXISTS都是短路的 – 一旦logging符合它被包含或过滤出来的条件,优化器移动到下一个logging。

无论是否匹配, LEFT JOIN都会join所有logging ,然后过滤掉所有不匹配的logging。 如果您的表格很大,并且/或者您有多个JOIN标准,则这可能非常耗费资源。

我通常尽可能地使用NOT EXISTSEXISTS 。 对于SQL Server, INNOT IN在语义上是等价的,并且可能更易于编写。 这些是在SQL Server中只能保证短路的唯一操作符。

我已经读过关于SQL Server的这个主题的最好的讨论就在这里 。

就我个人而言,我认为这是一个很大的“它取决于”。 我已经看到每种方法都超过其他方法的情况。

你最好的select是testing两个,看看哪个更好。 如果这种情况下,桌子总是很小,而且performance也不那么重要,那么我会select一个最清晰的方式(大多数人通常NOT EXISTS ),然后继续前进。

这个博客条目给出了不同的方式(不在, 外部应用左外连接除了不存在 )的例子,以达到相同的结果,并certificate不存在(左反半连接)是冷藏caching和温暖caching场景。

我一直想知道如何在OP描述的这些情况下使用我们删除的表上的索引。

假设我们有:

  table EMPLOYEE (emp_id int, name varchar) and table EMPLOYEE_LOCATION (emp_id int, loc_id int) 

在我的现实世界的例子中,我的表格更广泛,包含100万行+,我已经简化了架构的例子目的。

如果我想从EMPLOYEE_LOCATION中删除EMPLOYEE中没有对应的emp_id的行,我可以明显地使用Left outer技术或NOT IN,但是我想知道…

如果两个表都有带有emp_id的前导列的索引,那么尝试使用它们是否值得?

也许我可以把EMPLOYEE中的emp_id,EMPLOYEE_LOCATION中的emp_id,放到临时表中,并从我想要删除的临时表中获取emp_id。

然后,我可以循环这些emp_id的实际使用索引像这样:

 loop for each emp_id X to delete -- (this would be a cursor) DELETE EMPLOYEE_LOCATION WHERE emp_id = X 

我知道有光标的开销,但在我真正的例子中,我正在处理巨大的表,所以我认为明确使用索引是可取的。

回答 dba.stackexchange

我注意到NOT EXISTSLEFT JOIN ... WHERE IS NULL优于(但略微)的exceptionLEFT JOIN ... WHERE IS NULL是在使用链接服务器时

从检查执行计划看来, NOT EXISTS运算符是以嵌套循环方式执行的。 因此它是在每行的基础上执行(我认为是有道理的)。

演示此行为的示例执行计划: 在这里输入图像描述