现在的位置: 首页 > 综合 > 正文

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

2011年01月04日 ⁄ 综合 ⁄ 共 2319字 ⁄ 字号 评论关闭
文章目录

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

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 ,也是在实际情况中的使用,两者没有具体的公式

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

抱歉!评论已关闭.