代码之家  ›  专栏  ›  技术社区  ›  yaoweijq

为什么oracle optimizer没有消除这种情况?

  •  0
  • yaoweijq  · 技术社区  · 5 年前

    我对这个案子有疑问,但不清楚原因。

    请考虑以下sql:

    create table t1(tid int not null, t1 int not null);
    create table t2(t2 int not null, tname varchar(30) null);
    create unique index i_t2 on t2(t2);
    create or replace view v_1 as
    select t1.tid,t1.t1,max(t2.tname) as tname
    from t1 left join t2
    on t1.t1 = t2.t2
    group by t1.tid,t1.t1;
    

    然后检查执行计划中的select count(1)from vu 1,优化程序将消除t2:

    SQL> select count(1) from v_1;
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3243658773
    
    ----------------------------------------------------------------------------------
    | Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT     |           |     1 |       |     3  (34)| 00:00:01 |
    |   1 |  SORT AGGREGATE      |           |     1 |       |            |          |
    |   2 |   VIEW               | VM_NWVW_0 |     1 |       |     3  (34)| 00:00:01 |
    |   3 |    HASH GROUP BY     |           |     1 |    26 |     3  (34)| 00:00:01 |
    |   4 |     TABLE ACCESS FULL| T1        |     1 |    26 |     2   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------
    

    但是如果索引i\u t2在没有唯一属性的情况下被删除或重新创建,

    表t2未在执行计划中删除:

    SQL> drop index i_t2;
    
    Index dropped.
    
    SQL> select count(1) from v_1;
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2710188186
    
    -----------------------------------------------------------------------------------
    | Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |           |     1 |       |     5  (20)| 00:00:01 |
    |   1 |  SORT AGGREGATE       |           |     1 |       |            |          |
    |   2 |   VIEW                | VM_NWVW_0 |     1 |       |     5  (20)| 00:00:01 |
    |   3 |    HASH GROUP BY      |           |     1 |    39 |     5  (20)| 00:00:01 |
    |*  4 |     HASH JOIN OUTER   |           |     1 |    39 |     4   (0)| 00:00:01 |
    |   5 |      TABLE ACCESS FULL| T1        |     1 |    26 |     2   (0)| 00:00:01 |
    |   6 |      TABLE ACCESS FULL| T2        |     1 |    13 |     2   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------
    

    似乎即使去掉索引,

    从v1中选择计数(1)的结果也等于 从中选择计数(1)(从t1中选择tid,t1按tid分组,t1)

    为什么优化器在第二种情况下没有消除t2?

    是否有任何原则或实际数据实例说明这一点?

    0 回复  |  直到 5 年前
        1
  •  2
  •   BobC    5 年前

    这是一种称为连接消除的优化。因为t2.t2是惟一的,优化器知道从t1检索的每一行只能从t2检索一行。因为t2没有任何投影,所以不需要执行连接。 如果你这么做的话

    select tid, t1 from v_1;
    

    您将看到我们不执行联接。但是,如果我们从t2投影,则需要连接。