使用类型

时间:2015-06-11 13:37:44

标签: oracle oracle11g

我对Oracle 11g R2上的CBO有一个有趣的问题,我似乎无法解决。假设以下内容(请注意,为简洁起见,这是为了减少DDL);

create or replace object o_primary_key ( id number(38,0) );
create or replace type t_primary_key table of o_primary_key;

create table customer (
  customer_id number(38, 0) primary key,
  parent_customer_id number(38, 0),
  ... additional columns ommitted ...
)

create table orders (
  order_id number(38, 0) not null primary key,
  customer_id number(38, 0) not null,
  date_applied date not null,
  deleted_on date null,
  amount number(18, 9) not null,
  ... additional columns ommitted ...
)

index idx_orders_1 on orders (customer_id, date_applied, deleted_on, order_id);

index idx_customers_1 on customer (parent_customer_id, case when parent_customer_id is not null then customer_id else null end) compute statistics;

CUSTOMERS表有大约200,000行,ORDERS表有大约600万行。我有一个查询,如下面的内容和此查询的意图 是显示给定客户ID的所有订单,或者如果客户ID是父级,则显示其子级的所有订单。

with c_ids as (
  select 1 as id from dual union all
  select 2 as id from dual union all
  select 3 as id from dual
),
c_customer_ids as (
  select t.id customer_id,
         c.parent_customer_id joining_customer_id
  from   c_ids t
  join   customers c
  on     t.id = c.customer_id
  or     t.id = c.parent_customer_id
)
select   *
from     c_customer_ids
join     orders o
on       o.customer_id = c.joining_customer_id
where    o.date_applied bewteen '10/MAY/15' and '13/MAY/15'
and      o.deleted_on is null
order by o.customer_id,
         o.date_applied;

当我运行此查询时,CBO正确(我相信)决定使用CONCATENATION操作重写查询的OR部分,使其部分地针对CUSTOMER_ID和 然后作为第二次运行反对PARENT_CUSTOMER_ID。这两个使用查询都使用索引,并且一致获取的数量非常低(大约200)。

请注意,在我正在测试的情况下,我正在考虑 从总计600万行中的1,800行。

但是,当我运行这样的查询时,它会变得很有趣;

with c_customer_ids as (
  select t.id customer_id,
         c.parent_customer_id joining_customer_id
  from   table(t_primary_key(o_primary_key(1), o_primary_key(2), o_primary_key(3))) t
  join   customers c
  on     t.id = c.customer_id
  or     t.id = c.parent_customer_id
)
select   *
from     c_customer_ids
join     orders o
on       o.customer_id = c.joining_customer_id
where    o.date_applied bewteen '10/MAY/15' and '13/MAY/15'
and      o.deleted_on is null
order by o.customer_id,
         o.date_applied;

当使用类型来定义数字时,CBO决定错误地(我相信)使用ORDERS表上的全表扫描将其作为单个查询运行,因此获得者大约130,000并且 查询运行速度很慢。

为什么使用类型导致这种差异?

谢谢, 该隐

0 个答案:

没有答案