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

Oracle 优化使用列作为子查询的视图

ASKTOM 2019-07-11
327

问题描述

我读了一个有关此问题的问题,但不能解决我的问题。

P11 _ 问题 _ 标识: 1594885400346999596

通常,我们有一个表,该表具有几乎没有人使用的列。

然后我们把这张表放在一个视图下

create or replace view original_table as
select
    t.f1,
    t.f2,
    t.detail_id,
  ( select td.long_text from detail td where td.detail_id = t.detail_id ) long_text
from
   original_tab t
复制


在几乎所有情况下,都没有使用original_table.long_text,因此例如

select
   ot.f2
from
     original_table ot
join next_table nt on
nt.f1 = ot.f1
...
复制


用户可以用original_tab替换original_table,但这不是一个选项。

我们的经验是,视图中long_text列的存在会影响上面 (第二个) 查询的计划。

Oracle的哪个版本是这种情况?
为什么会发生这种情况?




专家解答

标量子查询最多可以每行运行一次 (子查询缓存可以减少这种情况)。

但这只有在你访问它的情况下才会发生!

例如 (在11.2.0.4上测试运行):

create table t1 as 
  select * from dba_objects
  where  object_type = 'TABLE';

create table t2 as 
  select * from dba_tables;
  
create or replace view vw as
  select object_name, owner, created, object_id,
         (select last_analyzed from t2 
          where  t2.table_name = t1.object_name
          and    t2.owner = t1.owner ) l
  from   t1;
  
set serveroutput off
alter session set statistics_level = all;
set feed only

select * from vw;

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  2zhnk50cnq4c7, child number 1
-------------------------------------
select * from vw

Plan hash value: 3472008848

-------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |
-------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |   1632 |
|*  1 |  TABLE ACCESS FULL| T2   |   1632 |      1 |   1566 |
|   2 |  TABLE ACCESS FULL| T1   |      1 |   1632 |   1632 |
-------------------------------------------------------------

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

   1 - filter(("T2"."TABLE_NAME"=:B1 AND "T2"."OWNER"=:B2))

Note
-----
   - dynamic sampling used for this statement (level=2)

set feed only
select object_name, owner from vw;

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  duqmnwhv9xzz2, child number 0
-------------------------------------
select object_name, owner from vw

Plan hash value: 3688435342

-------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |
-------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |   1632 |
|   1 |  TABLE ACCESS FULL| T1   |      1 |   1632 |   1632 |
-------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)
复制


注意第二次查询的计划中没有T2怎么出现?

如果您认为您的查询正在运行子查询-即使您尚未访问-那么请分享一个测试用例来演示这一点。这个测试用例应该看起来像我的上面。

即包括:

-创建表 (如果需要,插入)
-创建视图
-选择
-使用dbms_xplan生成的执行计划,如图所示
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论