oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。

场景:
需要获取部分数据集(视图)的业务时间最大值,希望只通过一条语句获取多个的最大值。
则使用select (视图1业务时间最大值),(视图2业务时间最大值),(视图3业务时间最大值) from dual
程序执行过程中,发现语句执行较慢,则进行sql调优。

使用子方式查询,获取最大值

子查询是一个嵌套在另一个查询语句中的查询语句。它可以被视为一个查询被包含在另一个查询中的过滤条件,可以在查询语句中的WHERE,FROM或SELECT子句中使用。子查询可以返回单个值、单个行或多个行,并且可以被用来解决复杂性问题或减少查询中的代码复杂性。

select (SELECT max(SJGXSJ) TIME_MAX
          FROM v_yewu1
         where SJGXSJ >= sysdate - 1
           and SJGXSJ < sysdate) AS TIME1,
       NULL AS TIME2,
       NULL AS TIME3,
       NULL AS TIME4,
       NULL AS TIME5
  from dual
 where 1 = 1

oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第1张图片
如图,效果很不理想。
如果是拿子查询的语句出来,单独查询,就会走时间索引,就很快。
oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第2张图片

使用union方式查询,获取最大值

oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第3张图片
改成union空表
oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第4张图片
union是合并两个查询的,怎么也会导致执行计划发生改变呢,第一时间想到的是union中去重导致的。然后我吧union 改成union all结果,执行计划还是很糟糕。
oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第5张图片

使用join方式查询,获取最大值

最后,把语句改成关联的形式,总算是满足了实际的业务需要。

select t1.TIME_MAX AS TIME1,
       t2.TIME_MAX AS TIME2,
       NULL        AS TIME3,
       NULL        AS TIME4,
       NULL        AS TIME5
  from (SELECT max(SJGXSJ) TIME_MAX
          FROM  v_yuwu1
         where SJGXSJ >= sysdate - 1
           and SJGXSJ < sysdate) t1,
       (SELECT max(SJGXSJ) TIME_MAX
          FROM v_yuwu2
         where SJGXSJ >= sysdate - 1
           and SJGXSJ < sysdate) t2a
 where 1 = 1

oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。_第6张图片

总结

sql执行过程中,视图查询,使用子查询、union或者多层视图嵌套,都可能会导致执行计划发生改变,多层视图嵌套结构的语句,where条件位置等都有可能导致执行计划发生改变,索引不生效的问题,这些应当尽量避免。sql调优过程中也可以使用些hint进行优化。使用视图查询,还是有明显的劣势,条件允许,尽量使用直接的sql语句查询,并且避免sql里面用到视图。

你可能感兴趣的:(oracle,数据库,sql调优,执行计划)