sql-server – 在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) 上述查询在三秒钟内完成. 假如上面的查询返回任何值,我们但愿存储进程为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#并再次举办陈设. 以是我的题目是,
以下是也许对您有所辅佐的具体信息,假如您必要任何具体信息,请奉告我们: >建设表和统计信息剧本以得到与我的沟通的打算 Slow plan using Brentozar Paste the plan 留意:两个查询都是沟通的(行使参数),独一的区别是EXISTS(我也许在匿名时犯了一些错误). 表建设剧本如下: http://pastebin.com/CgSHeqXc – 小桌子统计 办理要领正如 Paul White在他的博客文章中所表明的那样: Inside the Optimizer: Row Goals In Depth EXISTS引入了一个行方针,它更喜好NESTED LOOPS或MERGE JOIN而不是HASH MATCH
在您的查询中,这显然会引入嵌套轮回并删除并行性,从而导致打算速率变慢. 因此,您也许必要找到一种要领来重写查询,而无需行使查询中的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 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |