Oracle的Optimizer是否考虑了子查询的基础列?

时间:2019-01-05 03:26:08

标签: database oracle query-optimization oracle12c

假设您有这样的查询:

with subselect as (
   select foo_id 
     from foo
) 
select bar_id 
  from bar
  join subselect on foo_id = bar_id
 where foo_id = 1000

想象一下,您在foo_id上有一个索引。 Oracle的数据库是否足够聪明,可以在查询中使用“ where foo_id = 1000”行的索引?还是因为foo_id包装在子查询中,Oracle会丢失与该列相关的索引信息吗?

1 个答案:

答案 0 :(得分:0)

执行一个简单的测试:

create table foo as
select t.object_id as foo_id, t.* from all_objects t;

create table bar as
select t.object_id as bar_id, t.* from all_objects t;

create index foo_id_ix on foo(foo_id);

exec dbms_stats.GATHER_TABLE_STATS(ownname=>user, tabname=>'FOO', method_opt=>'FOR ALL INDEXED COLUMNS' );

explain plan for 
with subselect as (
   select foo_id 
     from foo
) 
select bar_id 
  from bar
  join subselect on foo_id = bar_id
 where foo_id = 1000;

 select * from table( DBMS_XPLAN.DISPLAY );

最后一次查询的结果是:

Plan hash value: 445248211

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |     1 |    10 |   366   (1)| 00:00:01 |
|   1 |  MERGE JOIN CARTESIAN|           |     1 |    10 |   366   (1)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL  | BAR       |     1 |     5 |   365   (1)| 00:00:01 |
|   3 |   BUFFER SORT        |           |     1 |     5 |     1   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN  | FOO_ID_IX |     1 |     5 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("BAR_ID"=1000)
   4 - access("FOO_ID"=1000)

在上面的示例中,Oracle使用|* 4 | INDEX RANGE SCAN使用索引:FOO_ID_IX作为过滤器4 - access("FOO_ID"=1000)

答案是:
 是的,Oracle的数据库足够智能,可以在查询中使用“其中foo_id = 1000”行的索引