Joe*_*eda 38 sql t-sql sql-server performance sql-server-2005
我刚刚通过阅读同事编写的代码了解到SQL Server中存在新的"EXCEPT"子句(有点晚了,我知道......).这真让我惊讶!
但后来我对它的使用有一些疑问:什么时候建议使用它?使用它与使用"AND NOT EXISTS ..."的相关查询之间是否存在性能差异?
在阅读了BOL中的EXCEPT文章之后,我认为它只是第二个选项的简写,但是当我用它重写了几个查询时(因为他们对我更熟悉的"AND NOT EXISTS"语法)然后检查了,我感到很惊讶.执行计划 - 惊喜!EXCEPT版本的执行计划更短,执行速度也更快.总是这样吗?
所以我想知道:使用这个强大的工具的准则是什么?
Qua*_*noi 37
EXCEPT将NULL值视为匹配.
这个查询:
WITH q (value) AS
(
SELECT NULL
UNION ALL
SELECT 1
),
p (value) AS
(
SELECT NULL
UNION ALL
SELECT 2
)
SELECT *
FROM q
WHERE value NOT IN
(
SELECT value
FROM p
)
Run Code Online (Sandbox Code Playgroud)
将返回一个空行集.
这个查询:
WITH q (value) AS
(
SELECT NULL
UNION ALL
SELECT 1
),
p (value) AS
(
SELECT NULL
UNION ALL
SELECT 2
)
SELECT *
FROM q
WHERE NOT EXISTS
(
SELECT NULL
FROM p
WHERE p.value = q.value
)
Run Code Online (Sandbox Code Playgroud)
将返回
NULL
1
Run Code Online (Sandbox Code Playgroud)
, 还有这个:
WITH q (value) AS
(
SELECT NULL
UNION ALL
SELECT 1
),
p (value) AS
(
SELECT NULL
UNION ALL
SELECT 2
)
SELECT *
FROM q
EXCEPT
SELECT *
FROM p
Run Code Online (Sandbox Code Playgroud)
将返回:
1
Run Code Online (Sandbox Code Playgroud)
递归中的EXCEPT子句中也允许使用递归引用CTE,但它的行为方式很奇怪:它返回除前一组的最后一行之外的所有内容,而不是除了整个前一组之外的所有内容:
WITH q (value) AS
(
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
),
rec (value) AS
(
SELECT value
FROM q
UNION ALL
SELECT *
FROM (
SELECT value
FROM q
EXCEPT
SELECT value
FROM rec
) q2
)
SELECT TOP 10 *
FROM rec
---
1
2
3
-- original set
1
2
-- everything except the last row of the previous set, that is 3
1
3
-- everything except the last row of the previous set, that is 2
1
2
-- everything except the last row of the previous set, that is 3, etc.
1
Run Code Online (Sandbox Code Playgroud)
SQL Server 开发人员必须忘记禁止它.
小智 8
我做了很多分析除了,不存在,不在和外连接.通常,左外连接是查找丢失行的最快,尤其是连接主键.如果您知道它将是select中返回的小列表,则In In可以非常快.
我使用EXCEPT来比较重写代码时返回的内容.运行旧代码保存结果.运行新代码保存结果,然后使用除捕获所有差异.这是一种快速简便的方法来查找差异,尤其是在需要获得包括null在内的所有差异时.非常适合即时轻松编码.
但是,每种情况都不同.我对我曾经指导过的每一位开发者说.试试吧.做各种各样的时间.试试吧,时间吧,做吧.
没有考虑 SQL Server 的执行计划。我总是发现,当出现性能问题时,当一种语法比另一种语法制定更好的执行计划时,这是完全任意的(从用户的角度来看,我确信算法编写者会理解为什么)。
在本例中,有关查询参数比较的某些操作允许 SQL 找出直接 select 语句无法找出的快捷方式。我确信这是算法的缺陷。换句话说,您可以在逻辑上插入相同的内容,但算法不会对存在的查询进行转换。有时这是因为能够可靠地计算出结果的算法比查询本身需要更长的执行时间,或者至少算法设计者是这么认为的。