SQL -- 使用联结还是子查询?
关于子查询,由来已久的传统观念认为,如果可以的话,使用联结会更好些。在某些情况下,该观点完全争取,但有时候在不同场合,根据不同考虑,使用时会有一定倾向性。下表讨论了决定性能权衡的某些问题,以及倾向于哪一种解决方案:
情况 |
倾向于 |
从子查询中返回的数值对于外部查询中的所有行是相同的 |
预查询。声明变量,然后选择需要的值放入变量中,这能使即将形成的子查询只执行一次,而不是对外部表中的每一条记录执行一次。事实上SQL Server中的优化器相当聪明,它一旦察觉到处于这样的情形,将为你进行预查询,但是别依赖它。为了以防万一,当你意识到这样的情形时,请执行你自己的预查询。 |
两个表都相对较小(例如:只有10 000条记录或者更少) |
子查询。不清楚确切的原因是什么,但是,经过实验可知,当所有的查找数据仅仅属于一、两个数据页时,查找比起联结花费的开销更少。 |
在考虑了所有的条件后,匹配将只返回一个值 |
子查询。同样,比起必须联结整张表来说,只找寻一条记录并代换它所需的开销要少得多。 |
在考虑了所有的条件后,匹配将只返回相对较少的值,并且,在查找列上没有索引 |
子查询。通常,比起散列联结来说,单独的一次或者甚至数次查找将花费较少的开销。 |
查找表相对较小,基表很大 |
若可以的话,则使用嵌套子查询;若联结相对于相关子查询,则使用联结。使用子查询时,查找只发生一次,因而其开销相对较小。然而,如果使用的是相关子查询,则查找将会循环许多次-----既如此,大多数情况此案联结将是更好的选择。 |
相关子查询与联结 |
联结。本质上,相关子查询将造成嵌套循环的情形。这会产生相当多的开销。多数情况下,他远远快于游标,但是,它比其他可能的选择方案要慢一些。 |
派生表与其他选择 |
派生表常常意味着大量的开销,因此需要谨慎使用。要知道,派生表只运行一次,随后就会驻留于内存中,因而,多数的开销存在于首次创建的过程中以及没有索引的较大结果集上。它们可能很快、也可能很慢,这取决于具体的情况。在进行编写派生表前要仔细考虑。 |
EXISTS与其他选择 |
EXISTS。不必针对同样的条件进行多次查找------但找到了特定行的一个匹配,将进入到下一个查找中,这能够极大地减少开销。 |
以上只是比较显著的情况而以,必定存在着形形色色不同的混合以及无穷无尽另外的情况。