暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle union all查询的两个部分之一的条件执行

askTom 2018-04-12
444

问题描述

我有两个复杂的,昂贵的查询,我已经执行了一个联合,所有这些查询都汇集在一起,以便在报告工具中使用



我有一个绑定变量,如果设置为一个值,则联合查询应执行联合的第一部分。如果将bind变量设置为第二个值,则应执行union查询的第二部分。



但是,当我查看跟踪和/或解释我的查询的计划时,存在来自联合查询的两个部分的成本。



这是我正在尝试做的简化版本:


    create table t1   
    as  
    select 'T1' as ttype, 'Gadget 1' as descr from dual  
    union all  
    select 'T2' as ttype, 'Gadget 2' as descr from dual  
    union all  
    select 'T3' as ttype, 'Gadget 3' as descr from dual;  
      
    create table t2   
    as  
    select 'T21' as ttype, 'Widget 1' as descr from dual  
    union all  
    select 'T22' as ttype, 'Widget 2' as descr from dual  
    union all  
    select 'T23' as ttype, 'Widget 3' as descr from dual;  
    3' as ttype, 'Widget 3' as descr from dual;  
复制



然后我的查询是:


    select ttype, descr from t1  
    where :P_Type='1'  
    union all  
    select ttype, descr from t2  
    where :P_Type='2';  
复制



我希望,如果我为P_Type提供绑定值 '1',那么CBO/查询实际上只会访问表t1 (表t2的基数/成本为零)。



但是,我看到的是来自两个表的成本和基数,无论我分配给bind变量的值如何



如何强制CBO/数据库 “修剪” 查询的那些部分,其中条件/绑定值指示联合查询的一部分是不相关的?



我不想把它分成两个不同的查询,因为报告上有很多格式,我需要为这两个查询复制。



非常感谢您的反馈...



Oracle数据库企业版12.1.0.2,带SQL调优选项

专家解答

你在看estimated中的行explain计划,或者actual中的行execution计划?

请记住,解释计划成本和基数是估计。这些是在不知道绑定值是什么的情况下生成的。

Bind变量peeking允许优化器根据输入调整计划。但在这种情况下没关系。无论您分配给什么值,计划都是相同的: P_Type。

例如,在下面的执行计划中,请注意开始和A行对于t2都是零。

步骤2和4中的滤波器操作短路处理。如果条件为true,则数据库仅在其下方进行完整扫描:

create table t1 as  
  select 'T1' as ttype, 'Gadget 1' as descr from dual  
  union all  
  select 'T2' as ttype, 'Gadget 2' as descr from dual  
  union all  
  select 'T3' as ttype, 'Gadget 3' as descr from dual;  
    
create table t2 as  
  select 'T21' as ttype, 'Widget 1' as descr from dual  
  union all  
  select 'T22' as ttype, 'Widget 2' as descr from dual  
  union all  
  select 'T23' as ttype, 'Widget 3' as descr from dual;  
    
set serveroutput off

var p_type varchar2(1);
exec :p_type := '1';

select /*+ gather_plan_statistics */ttype, descr from t1  
where :P_Type='1'  
union all  
select ttype, descr from t2  
where :P_Type='2';

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST +COST'));

----------------------------------------------------------------------------   
| Id  | Operation           | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   
----------------------------------------------------------------------------   
|   0 | SELECT STATEMENT    |      |      1 |        |     4 (100)|      3 |   
|   1 |  UNION-ALL          |      |      1 |        |            |      3 |   
|*  2 |   FILTER            |      |      1 |        |            |      3 |   
|   3 |    TABLE ACCESS FULL| T1   |      1 |      3 |     2   (0)|      3 |   
|*  4 |   FILTER            |      |      1 |        |            |      0 |   
|   5 |    TABLE ACCESS FULL| T2   |      0 |      3 |     2   (0)|      0 |   
----------------------------------------------------------------------------

Predicate Information (identified by operation id):                            
---------------------------------------------------                            
                                                                               
   2 - filter(:P_TYPE='1')                                                     
   4 - filter(:P_TYPE='2')  
复制


所以它已经修剪了查询的执行!

记住: 要评估一个计划,你必须看看它所做的实际工作。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论