Sql 为什么oracle optimizer不消除这种情况?

Sql 为什么oracle optimizer不消除这种情况?,sql,oracle,optimization,Sql,Oracle,Optimization,我怀疑这个案子,但不清楚为什么 考虑以下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 t

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

考虑以下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中select count1的执行计划,优化器消除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 |
-----------------------------------------------------------------------------------
似乎即使删除了索引

从v_1中选择count1的结果也等于 从选择tid中选择count1,从t1组中按tid选择t1,t1

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

是否有任何原则或实际数据示例来描述这一点?
谢谢:

这是一个名为加入消除的优化。因为t2.t2是唯一的,所以优化器知道从t1检索到的每一行只能从t2检索到一行。由于没有从t2投影任何内容,因此不需要执行联接。 如果你这样做

select tid, t1 from v_1;

您将看到我们不执行联接。但是,如果我们从t2开始项目,则需要加入。

谢谢。我很清楚第一个案例。对于第二种情况,我不清楚为什么t2没有被消除。@BobC在没有唯一属性的情况下重新创建,这就是为什么。你说因为t2.t2是唯一的,但是OP取消了这个假设。在第二种情况下,优化器不知道联接将产生多少行。因此,需要完成联接。@BobC视图具有group byclause@yaoweijq由于外部查询仅获取分组行的计数,因此即使t2索引是非唯一的,也不需要加入t2。如果我错了,我相信鲍勃会说为什么这是必要的。但就目前而言,我认为您只是发现了Oracle尚未进行的优化。我想这可能是个错误,但我不指望有人会承认。您可能想看看,因为您的用法有点像子查询。