zoukankan      html  css  js  c++  java
  • 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 ,也是在实际情况中的使用,两者没有具体的公式

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

  • 相关阅读:
    2012 人民搜索 实习生招聘 笔试题(转)
    招行两地一卡——PayPal美元兑换人民币的最佳解决方案
    PHP上传图片类
    PHP获取随机数
    Linux下解压RAR软件下载和解压.zip和.rar文件
    Zend Framework学习(1)简介
    编程指导
    Zend Framework数据库操作总结
    Zend Framework学习(4)之前端控制器
    参数是否为FALSE的区别
  • 原文地址:https://www.cnblogs.com/zping/p/1302208.html
Copyright © 2011-2022 走看看