加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql-server – 在IF EXISTS中包装查询使得它非常慢

发布时间:2021-05-30 19:43:43 所属栏目:编程 来源:网络整理
导读:我有以下查询: select databasename from somedb.dbo.bigtable l where databasename ='someval' and source 'kt'and not exists(select 1 from dbo.smalltable c where c.source=l.source) 上述查询在三秒钟内完成. 假如上面的查询返回任何值,我们但愿存储

我有以下查询:

select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)

上述查询在三秒钟内完成.

假如上面的查询返回任何值,我们但愿存储进程为EXIT,以是我重写如下:

If Exists(
select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
)
Begin
Raiserror('Source missing',16,1)
Return
End

然而这必要10分钟.

我可以像下面一样重写上面的查询,它也可以在不到3秒的时刻内完成:

select databasename 
from somedb.dbo.bigtable l where databasename ='someval' and source  <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source
if @@rowcount >0
Begin
Raiserror('Source missing',1)
Return
End

上面重写的题目是上面的查询是更大的存储进程的一部门,它返回多个功效集.在C#中,我们遍历每个功效集并举办一些处理赏罚.

上面返回一个空的功效集,以是假如我回收这种要领,我必需改变我的C#并再次举办陈设.

以是我的题目是,

why does using just IF EXISTS changes the plan to take so much time?

以下是也许对您有所辅佐的具体信息,假如您必要任何具体信息,请奉告我们:

>建设表和统计信息剧本以得到与我的沟通的打算
>慢执行打算
>快速执行打算

Slow plan using Brentozar Paste the plan
Fast Plan using Brentozar Paste the plan

留意:两个查询都是沟通的(行使参数),独一的区别是EXISTS(我也许在匿名时犯了一些错误).

表建设剧本如下:

http://pastebin.com/CgSHeqXc – 小桌子统计
http://pastebin.com/GUu9KfpS – 大表统计

办理要领

正如 Paul White在他的博客文章中所表明的那样: Inside the Optimizer: Row Goals In Depth EXISTS引入了一个行方针,它更喜好NESTED LOOPS或MERGE JOIN而不是HASH MATCH

As a final example,consider that a logical semi-join (such as a
sub-query introduced with EXISTS) shares the overall theme: it should
be optimised to find the first matching row quickly.

在您的查询中,这显然会引入嵌套轮回并删除并行性,从而导致打算速率变慢.

因此,您也许必要找到一种要领来重写查询,而无需行使查询中的NOT EXISTS.

您也许会行使LEFT OUTER JOIN重写您的查询并通过测试NULL搜查smalltable中没有行

If EXISTS(
    SELECT databasename
    FROM somedb.dbo.bigtable l
    LEFT JOIN dbo.smalltable c ON c.source = l.source
    WHERE databasename = 'someval'
    AND source <> 'kt'
    AND c.source IS NULL
)

您也可以行使EXCEPT查询,详细取决于您必要较量的字段数,如下所示:

If EXISTS(
   SELECT source
   FROM somedb.dbo.bigtable l
   WHERE databasename = 'someval'
   AND source <> 'kt'

   EXCEPT

   SELECT source
   FROM dbo.smalltable
)

请留意,Aaron Bertrand有一篇博文providing reasons why he prefers NOT EXISTS,您应该阅读以相识其他要领是否更好,并相识NULL值的隐藏正确性题目.

相干Q&答:IF EXISTS taking longer than embedded select statement

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读