Oracle 优化器足够聪明,可以消除未使用的列,前提是这样做不会影响查询结果(也就是说,如果没有它们,查询在逻辑上是相同的)。如果可以保证这样做不会影响结果,它可以消除整个表和连接。是否这样做取决于查询和表上定义的约束。
在您的示例中,如果co.customer_number 是强制性的并且以ci.customer_number 作为其父级的外键,则它可能能够消除customer_info,因为customer_info 中必须始终只有一行。
演示:
create table test_parent
( id integer primary key
, parent_name varchar2(30) not null );
create table test_child
( child_id integer primary key
, parent_id references test_parent not null
, child_name varchar2(30) not null );
insert into test_parent values (1, 'Test parent 1');
insert into test_parent values (2, 'Test parent 2');
insert into test_child values (1, 1, 'Test child 1');
insert into test_child values (2, 2, 'Test child 2');
insert into test_child values (3, 1, 'Test child 3');
insert into test_child values (4, 2, 'Test child 4');
commit;
select c.child_id, c.child_name
from test_child c
join test_parent p on p.id = c.parent_id;
执行计划:
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 64 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS STORAGE FULL| TEST_CHILD | 4 | 64 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
添加 p.parent name 需要加入,所以计划改变:
select c.child_id, c.child_name, p.parent_name
from test_child c
join test_parent p on p.id = c.parent_id;
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 144 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 4 | 144 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| TEST_PARENT | 2 | 34 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | SYS_C001668561 | 2 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 4 | 76 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS STORAGE FULL | TEST_CHILD | 4 | 76 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
编辑:标量子查询示例 - 视图将表用于一列:
create or replace view customer_order_info1 as
select ch.child_id
, ch.child_name
, ( select pa.parent_name from test_parent pa
where pa.id = ch.parent_id ) as parent_name
from test_child ch;
但如果我不在视图查询中使用该列:
select c1.child_id, c1.child_name
from customer_order_info1 c1
我得到了这个执行计划:
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 82 | 2460 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS STORAGE FULL| TEST_CHILD | 82 | 2460 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
(test_parent 无法访问。)