SQL 语句优化 --将Exists转换成 inner join 语句来选择正确的执行计划

    这段时间优化时,发现一个语句执行时间很长,效率很低,语句如下:

select id,field015,field016,field017,field001,field020,field010,field014,field011,field013,field004,field018,
field005,field007,field003,
null ,requestid from ufv3a7n71178865841875  tbalias where requestid inselect id from workflowbase wb where wb.isdelete<>1  and isfinished=0 ) and  
exists (select 'X' from Permissiondetail p where p.objid=tbalias.requestid and p.objtable='workflowbase' and ((p.userid='40282c48177be3a001177fefe73843d8'or (( p.isalluser=1 or p.orgid='40288a7d0f55fb5a010f569c2bf01205'
and (p.minseclevel <= 10 and ((( p.maxseclevel is not nulland (10<= p.maxseclevel)) or (p.maxseclevel is null)))))) 
order by field017 desc,id desc

执行计划: 

执行结果: 

(1578 行受影响)
表 
'workflowbase'。扫描计数 0,逻辑读取 34932 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 
'permissiondetail'。扫描计数 8145,逻辑读取 48196 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 
'ufv3a7n71178865841875'。扫描计数 1,逻辑读取 576 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

 

  将 exists语句转换成inner join 语句,改成后的语句如下:

复制代码
select distinct tbalias.id,field015,field016,field017,field001,field020,field010,field014,field011,field013,field004,field018,
field005,field007,field003,
null ,requestid from ufv3a7n71178865841875  tbalias
inner join workflowbase wb on wb.id=tbalias.requestid and wb.isdelete<>1  and isfinished=0 
inner join  Permissiondetail p on p.objid=tbalias.requestid and p.objtable='workflowbase' and 
((p.userid
='40282c48177be3a001177fefe73843d8'or (( p.isalluser=1 or p.orgid='40288a7d0f55fb5a010f569c2bf01205'
and (p.minseclevel <= 10 and ((( p.maxseclevel is not nulland (10<= p.maxseclevel)) or (p.maxseclevel is null)))))
order by field017 desc,id desc
复制代码

执行计划:

执行结果:

(1578 行受影响)
表 
'permissiondetail'。扫描计数 2988,逻辑读取 17298 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 
'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 
'ufv3a7n71178865841875'。扫描计数 1,逻辑读取 576 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 
'workflowbase'。扫描计数 1,逻辑读取 1425 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

 

   通过使用 inner join 替换 exists ,我们发现执行计划里将 哈希联结(Hash join)换成了 嵌套循环(Nested Loops) ,IO次数明细减少。

总结:

     以前写过一优化文章" SQL优化--使用 EXISTS 代替 IN 和 关联查询(inner join) ",提示用exists替换inner join ,这个替换是有前提条件,要经过测试的,今天我们又使用 inner join 替换 exists ,也是在实际情况中的使用,两者没有具体的公式

      目的:是在特定情况下让优化器能使用正确的执行计划。

posted @   zping  阅读(3826)  评论(2编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示