我对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;
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
当我运行这个查询时,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;
Run Code Online (Sandbox Code Playgroud)
当使用类型来定义数字时,CBO决定错误地(我相信)使用ORDERS表上的全表扫描将其作为单个查询运行,因此consisent获得大约130,000并且查询运行得更慢.
为什么使用这种类型会造成这样的差异?
谢谢,该隐
| 归档时间: |
|
| 查看次数: |
60 次 |
| 最近记录: |