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

时间:2024-03-31 19:42:16

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

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 in( select 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 null) and (10<= p.maxseclevel)) or (p.maxseclevel is null)))))) 
order by field017 desc,id desc

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

执行计划: 

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

(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 语句,改成后的语句如下:

SQL 语句优化 --将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 null) and (10<= p.maxseclevel)) or (p.maxseclevel is null)))))
order by field017 desc,id desc

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

执行计划:

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

执行结果:

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

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

转载于:https://my.oschina.net/ldm95/blog/745886