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

Oracle 按表标识符从联合视图中选择

askTom 2018-09-17
168

问题描述

嗨,
我有这样的观点
create view V_TAB as 
(select 1 as id, value from TAB1
 union all
 select 2 as id, value from TAB2
);
复制

我希望Oracle能够优化以下查询并仅在一个表上执行选择,因为id值作为恒定值提供-

select * from V_TAB where id=1;
复制

但是执行计划显示从两个基础表中进行选择-

------------------------------------------------------
| Id  | Operation                | Name              |
------------------------------------------------------
|   0 | SELECT STATEMENT         |                   |
|   1 |  VIEW                    |                   |
|   2 |   UNION-ALL              |                   |
|   3 |     TABLE ACCESS FULL    | TAB1              |
|*  4 |    FILTER                |                   |
|   5 |     TABLE ACCESS FULL    | TAB2              |
------------------------------------------------------
复制


还有什么有趣的-它使用奇怪的过滤表达-
谓词信息 (由操作id标识):
---------------------------------------------------
4-过滤器 (NULL不为NULL)

它看起来像Oracle optimizer忽略了基于视图的常数值的表限制的可能性。可能有一些变通办法吗?我的目标是在几个相似的表的顶部创建一个单一的视图,而不是表名中不同的几个select语句使用一个由表id参数化的select语句。我想最小化我的代码的另一个词,同时不要在不必要的表上添加扫描。
即,而不是
if p_id=1 then
  select count(*) into cnt from TAB1;
elsif p_id=2 then
  select count(*) into cnt from TAB2;
else
  cnt := 0;
end if;
复制

使用简单的代码
select count(*) into cnt from V_TAB where id=v_id;
复制


专家解答

但是数据库is能够根据需要优化您的查询!

虽然这两个表都可能出现在您的计划中,但它只在运行时访问一个。

谓词NULL不为NULL => false。这意味着它不执行此过滤器下的操作。

您可以通过查看execution计划查询。这显示了它的运行时统计信息:

create or replace view V_TAB as 
(select 1 as id, dummy from dual
 union all
 select 2 as id, dummy from dual
);
set serveroutput off

select /*+ gather_plan_statistics */* from V_TAB where id=1;

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

PLAN_TABLE_OUTPUT                                                   
SQL_ID  66w0ahf4hk0p4, child number 0                               
-------------------------------------                               
select /*+ gather_plan_statistics */* from V_TAB where id=2         
                                                                    
Plan hash value: 3824994890                                         
                                                                    
-----------------------------------------------------------------   
| Id  | Operation            | Name  | Starts | E-Rows | A-Rows |   
-----------------------------------------------------------------   
|   0 | SELECT STATEMENT     |       |      1 |        |      1 |   
|   1 |  VIEW                | V_TAB |      1 |      2 |      1 |   
|   2 |   UNION-ALL          |       |      1 |        |      1 |   
|*  3 |    FILTER            |       |      1 |        |      0 |   
|   4 |     TABLE ACCESS FULL| DUAL  |      0 |      1 |      0 |   
|   5 |    TABLE ACCESS FULL | DUAL  |      1 |      1 |      1 |   
-----------------------------------------------------------------   
                                                                    
Predicate Information (identified by operation id):                 
---------------------------------------------------                 
                                                                    
   3 - filter(NULL IS NOT NULL)                                     
                                   
复制


请注意,对于Id 4,开始列和A行列如何显示零?这意味着双重扫描从未发生过!
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论