Sql 为什么oracle optimizer不消除这种情况?
我怀疑这个案子,但不清楚为什么 考虑以下sql: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
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尚未进行的优化。我想这可能是个错误,但我不指望有人会承认。您可能想看看,因为您的用法有点像子查询。