于节点2上发现一个sql,其结构如下:
select distinct t.attr, t.item
from a t
where attr = :1
  and (pro = :2 or exists
       (select 1
          from b hps
         where hps.pro = :3
           and t.pro = hps.sub_pro))
鉴于以往的经验,一开始就觉得子查询中的连接谓词or有问题。
注:
表a有50多万条记录,attr和pro上分别有索引;表b有10万条记录,pro上有单独索引,同时(pro,sub_pro)组成unique索引;
同时表a上的attr,pro字段的分布情况如下,对于表a,pro字段的选择性比attr高出了很多
SQL> select count(distinct pro),count(distinct attr) from a;

COUNT(DISTINCT pro)           COUNT(DISTINCT attr)
------------------------- ---------------------------
          164067                         716

先通过set autotrace traceonly查看一把其执行计划和consistent gets
--------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                        |    63 |   945 |    83   (2)| 00:00:01 |
|   1 |  HASH UNIQUE                  |                        |    63 |   945 |    83   (2)| 00:00:01 |
|*  2 |   FILTER                      |                        |       |       |            |          |
|   3 |    TABLE ACCESS BY INDEX ROWID| a                      |  1268 | 19020 |    82   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | idx_a_attr             |  1268 |       |     8   (0)| 00:00:01 |
|*  5 |    INDEX UNIQUE SCAN          | idx_b_un_pro_sub       |     1 |    12 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("pro"=TO_NUMBER(:B) OR  EXISTS (SELECT 0 FROM "b" "HPS" WHERE
              "HPS"."SUB_pro"=:B1 AND "HPS"."pro"=TO_NUMBER(:C)))
   4 - access("attr"=TO_NUMBER(:A))
   5 - access("HPS"."pro"=TO_NUMBER(:C) AND "HPS"."SUB_pro"=:B1)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       4690  consistent gets
          0  physical reads
          0  redo size
        589  bytes sent via SQL*Net to client
        487  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

从执行计划看出,访问表a的时候选择了attr上的索引,实际效果不佳,逻辑读有4690;
通过等价改写后的sql如下,去除了谓词or,改用了union
select distinct t.attr, t.item
       from a t
      where attr = :a
        and pro = :b
union
select distinct t.attr, t.item
       from a t
      where attr = :a
            and exists
             (select 1
                from b hps
               where hps.pro = :c
                 and t.pro = hps.sub_pro)
改写后的sql的执行计划如下               
--------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                        |     6 |   150 |    16  (75)| 00:00:01 |
|   1 |  SORT UNIQUE                  |                        |     6 |   150 |    16  (75)| 00:00:01 |
|   2 |   UNION-ALL                   |                        |       |       |            |          |
|*  3 |    TABLE ACCESS BY INDEX ROWID| a                      |     1 |    15 |     4   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | idx_a_pro              |     3 |       |     3   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS BY INDEX ROWID| a                      |     1 |    15 |     3   (0)| 00:00:01 |
|   6 |     NESTED LOOPS              |                        |     5 |   135 |    10  (10)| 00:00:01 |
|   7 |      SORT UNIQUE              |                        |     5 |    60 |     2   (0)| 00:00:01 |
|*  8 |       INDEX RANGE SCAN        | idx_b_un_pro_sub       |     5 |    60 |     2   (0)| 00:00:01 |
|*  9 |      INDEX RANGE SCAN         | idx_a_pro              |     3 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter("attr"=TO_NUMBER(:A))
   4 - access("pro"=TO_NUMBER(:B))
   5 - filter("attr"=TO_NUMBER(:A))
   8 - access("HPS"."pro"=TO_NUMBER(:C))
   9 - access("T"."pro"="HPS"."SUB_pro")

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         24  consistent gets
          0  physical reads
          0  redo size
        589  bytes sent via SQL*Net to client
        487  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
          1  rows processed
访问表a时选择了pro上的索引,虽然增加了一次访问次数,但是逻辑读却下降到了24.

转载于:https://blog.51cto.com/xmffw/618156

优化拥有谓词or的子查询相关推荐

  1. SQL优化(三):子查询和IN,EXISTS用法和优化方法

    用法 1. 与IN结合使用 子查询与IN结合使用时,通常通过子查询查询出某个表单列的值,然后作为外层的SELECT的IN查询的数据源,如下,查询今天进行了购物的用户列表,首先通过子查询在订单表t_or ...

  2. 标量子查询产生的SQL性能瓶颈,该怎么合理优化?

    来自:DBAplus社群 作者介绍 郝昊喆,新炬网络数据库专家.擅长数据库方面的开发.整体架构及复杂SQL的调优,参与了多个行业核心系统的优化工作,目前专注于对开源技术.自动化运维和性能调优技术的研究 ...

  3. mysql semi join_MySQL 通过semi join 优化子查询

    半连接是MySQL 5.6.5引入的,多在子查询exists中使用,对外部row source的每个键值,查找到内部row source匹配的第一个键值后就返回,如果找到就不用再查找内部row sou ...

  4. mysql in 原理_深入理解MySql子查询IN的执行和优化

    IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...

  5. SQL优化之一则MySQL中的DELETE、UPDATE 子查询的锁机制失效案例

    关注"数据和云",精彩不容错过 前言 开发与维护人员避免不了与 in/exists.not in/not exists 子查询打交道,接触过的人可能知道 in/exists.not ...

  6. SQL Sever 子查询与嵌套查询

    数据库表 1.带 in 的嵌套查询 查询Student表 并且 Sno 在 SC表中有 select * from Student where Sno in(select Sno from SC) 2 ...

  7. 浅谈 MySQL 子查询及其优化

    2019独角兽企业重金招聘Python工程师标准>>> 使用过oracle或者其他关系数据库的DBA或者开发人员都有这样的经验,在子查询上都认为数据库已经做过优化,能够很好的选择驱动 ...

  8. oracle子查询不减少数据,Oracle性能优化-子查询到特殊问题

    编辑手记:前面我们介绍常用的子查询优化方法,但总有一些情况时在规律之外.谨慎处理方能不掉坑. 前文回顾: 作者简介:韩锋 精通包括Oracle.MySQL.informix等多种关系型数据库,有丰富的 ...

  9. mysql子查询缺点_[慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

    它的执行计划如下,请注意看关键词"DEPENDENT SUBQUERY": id  select_type         table   type            poss ...

最新文章

  1. 没做领导的时候,觉得领导都是傻X!做了领导之后觉得下属才是傻X!
  2. 轻量级数据库Sqlite的使用
  3. 面试官:Maven 的这 7 个问题你思考过没有?
  4. grpc ssl使用
  5. buck电路 dac stm32_STM32定时器学习---基本定时器
  6. 多进程event通信
  7. dede image.class.php,DEDE模板下载织梦DEDE 核心类TypeLink.class.php功能剖析
  8. Happy Mid-Autumn Festival !
  9. 重写 geturl Openlayers中使用TileCache加载预切割图片作为基础地图图层
  10. R语言报错:Error in scan
  11. 嵌入式Linux应用开发完全手册 pdf 韦东山
  12. LaTeX编写IEEE会议论文字体报错、且参考文献中会议/期刊的名字没有斜体的问题解决
  13. 电动按摩帖芯片FH8B23S16B单片机为什么这么多人用?
  14. java高级(java高级工程师证书)
  15. 动态仙人掌 系列题解之二——3465: 动态仙人掌 II
  16. C#为什么读作C Sharp
  17. 美国陪审团裁定福特向车祸遇难者家属赔偿17亿美元
  18. Tableau学习Step2一数据文件的读取与统计图、表的概述
  19. 【Argoverse 1 Motion Forecasting Dataset】轨迹预测数据集简介
  20. my ReadAnimal_hamster

热门文章

  1. 【深入浅出-JVM】(序)
  2. putty-psftp
  3. Docker Toolbox替换默认docker machine的存储位置
  4. 线程间通信共享变量和queue
  5. C#程序输出信息到调试窗口的几种方式
  6. Java集合类学习-LinkedList, ArrayList, Stack, Queue, Vector
  7. mysql数据库千万级别数据的查询优化和分页测试
  8. log4j用于读取.xml文件的出现了错误,类加载器.getResource(user.xml).getPath()返回路径空格变成了%20...
  9. PowerDesigner使用教程【转】
  10. 在MAC上搭建eclipse+android开发环境以及eclipse的svn插件的安装