tec*_*rer 7 performance sql-server query
为什么
SELECT Barraportfolioname
FROM portfolio
WHERE id IN (SELECT DISTINCT i1.portfolioid
FROM Import i1
LEFT OUTER JOIN Import i2
ON i1.PortfolioID = i2.PortfolioID
AND i2.ImportSetID = 82
WHERE i1.ImportSetID = 83
AND i2.ID IS NULL)
Run Code Online (Sandbox Code Playgroud)
需要 0 秒,而以下查询需要 5 秒。
SELECT DISTINCT p.BarraPortfolioName AS name
FROM Import i1
INNER JOIN Portfolio p
ON p.ID = i1.PortfolioID
LEFT OUTER JOIN Import i2
ON i1.PortfolioID = i2.PortfolioID
AND i2.ImportSetID = 82
WHERE i1.ImportSetID = 83
AND i2.ID IS NULL;
Run Code Online (Sandbox Code Playgroud)
我正在使用 SQL Server。这两个表在查询中使用的所有列上都有索引,即portfolioid、id、importsetid。
由 gbn 编辑,基于 OP 评论
他们说:
这比前两个查询要好得多。
select
BarraPortfolioName
from
(
select distinct p.BarraPortfolioName,portfolioid
from
import i1
inner join
portfolio p on p.id=i1.portfolioid
where
importsetid = ?
) as p1
left outer join
(
select distinct portfolioid
from import
where importsetid = ?
) as p2 on p1.portfolioid = p2.portfolioid
where
p2.portfolioid is null
Run Code Online (Sandbox Code Playgroud)
这假设两者都给出相同的结果
第一个是“半连接”,因为 IN(子查询)(不需要 DISTINCT)
这意味着子查询可以“短路”
第二个是外部连接,然后是限制,然后是 DISTINCT 聚合。
这是 3 个主要的离散操作
即使在子查询中使用外连接,这种“短路”也是造成差异的主要原因。
对于更简单的查询,第二个查询将优化为与第一个查询相同的计划,因为它在语义上是相同的。版本越晚等的可能性越大
有关更多信息,请参阅此内容(相同的逻辑,只是颠倒了):与索引相关的 NOT 逻辑的使用
这是关于SO 用户 Quassnoi 在他的网站上的“IN vs. JOIN vs. EXISTS”
还有一个类似的 SO 示例:https : //stackoverflow.com/a/7221395/27535
如果您在 BarraPortfolioName 上没有唯一索引,则需要检查所有索引是否有重复项,这在第一个查询中是不必要的,因为您的 IN 子句会为您处理该索引。
尝试创建一个唯一索引(或约束)并看看这是否有效。或者通过删除不同的并将其放在GROUP BY p.id, p.BarraPortfolioName末尾来更改第二个脚本。这应该会让区分过程短路。