左外连接上的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更好。
EXISTS
和NOT EXISTS
都是短路的 – 一旦logging符合它被包含或过滤出来的条件,优化器移动到下一个logging。
无论是否匹配, LEFT JOIN
都会join所有logging ,然后过滤掉所有不匹配的logging。 如果您的表格很大,并且/或者您有多个JOIN
标准,则这可能非常耗费资源。
我通常尽可能地使用NOT EXISTS
和EXISTS
。 对于SQL Server, IN
和NOT 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 EXISTS
在LEFT JOIN ... WHERE IS NULL
优于(但略微)的exceptionLEFT JOIN ... WHERE IS NULL
是在使用链接服务器时 。
从检查执行计划看来, NOT EXISTS
运算符是以嵌套循环方式执行的。 因此它是在每行的基础上执行(我认为是有道理的)。
演示此行为的示例执行计划: