我的声明需要 10秒才能对表X中的10k项目执行:
版本1
SELECT *
FROM X
WHERE pk = 77843
AND (a IS NULL OR a NOT IN (SELECT DISTINCT(b)
FROM X
WHERE pk = 77843
AND l IS NOT NULL))
子查询是不相关的,这意味着它没有引用外部查询。这意味着子查询只应执行一次。
版本2:
现在,如果我提取子查询并预先执行计算,则查询将在< 1s。
DECLARE @listOfb table (id int)
INSERT INTO @listOfb(id)
(SELECT DISTINCT(b) as Numbers
FROM X
WHERE pk = 77843
AND l IS NOT NULL)
SELECT *
FROM X
WHERE pk = 77843
AND (a IS NULL OR a NOT IN (SELECT * FROM @listOfb))
那么为什么版本2比版本1快得多?
更新
我添加了(我认为所谓的)版本1的执行计划: 该查询正在删除大约10k行。
答案 0 :(得分:1)
尝试使用公用表表达式和UNION:
;WITH CTE
AS
(
SELECT *
FROM X
WHERE pk = 77843
)
SELECT *
FROM CTE
WHERE a IS NULL
UNION ALL
SELECT *
FROM CTE C1
WHERE a IS NOT NULL AND
NOT EXISTS (SELECT * FROM CTE C2 WHERE C1.a = C2.b AND l IS NULL)
答案 1 :(得分:1)
您应该查看此article
我没有相同的服务器版本,但我想尝试的是解锁x'在主查询上还有子查询。
SELECT *
FROM X (NOLOCK)
WHERE pk = 77843
根据我的小经验,取决于表格大小及其上的索引,我发现有时会在同一个表格中查询两次时的性能差异(特别是在条件相同的情况下' pk = 77843'和/或更新/删除操作)。
关于你的上一条评论。我从执行计划中看不到多次执行子查询的情况。在我看来,第一个index_seek锁定pk列[主查询],并在同一列上到达第二个index_seek [子查询]时(我猜我可以& #39; t看到屏幕截图中的所有细节,导致性能问题。
但是,当你分别执行这两个查询(条件几乎相同)时,你会有更好的表现。