首页 > 解决方案 > 为什么 oracle 优化器不消除这种情况?

问题描述

我怀疑这个案子,但不清楚为什么。

考虑以下 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;

然后检查从 v_1 中选择 count(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_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 |
-----------------------------------------------------------------------------------

似乎即使删除了索引,

select count(1) from v_1 的结果也等于 select count(1) from (select tid,t1 from t1 group by tid,t1)

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

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

标签: sqloracleoptimization

解决方案


这是一种称为联接消除的优化。因为 t2.t2 我们是唯一的,优化器知道从 t1 检索的每一行只能从 t2 检索一行。由于 t2 没有投影,因此无需执行连接。如果你这样做

select tid, t1 from v_1;

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


推荐阅读