一个典型的数据仓库查询:
这个查询中sales 是事实表 , 一般很大。
products , customers , channels是维度表 , 一般很小,可以有冗余。
sh@ prod1> explain plan for 2 select sum( s.quantity_sold ) , sum( s.amount_sold ) from sales s , products p , customers c , channels ch 3 where 4 s.prod_id = p.prod_id and 5 s.cust_id = c.cust_id and 6 s.channel_id = ch.channel_id and 7 p.prod_name = 'y box' and 8 c.cust_first_name = 'abigail' and 9 ch.channel_desc = 'direct_sales' ; explained.
执行计划如下:
sh@ prod1> select * from table(dbms_xplan.display) ;
plan_table_output
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
plan hash value: 2309889988
--------------------------------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time | pstart| pstop |
--------------------------------------------------------------------------------------------------------------------------
| 0 | select statement | | 1 | 75 | 784 (1)| 00:00:10 | | |
| 1 | sort aggregate | | 1 | 75 | | | | |
|* 2 | hash join | | 20 | 1500 | 784 (1)| 00:00:10 | | |
|* 3 | table access full | customers | 43 | 516 | 405 (1)| 00:00:05 | | |
| 4 | nested loops | | | | | | | |
| 5 | nested loops | | 3235 | 199k| 378 (0)| 00:00:05 | | |
| 6 | merge join cartesian | | 1 | 43 | 6 (0)| 00:00:01 | | |
|* 7 | table access full | channels | 1 | 13 | 3 (0)| 00:00:01 | | |
| 8 | buffer sort | | 1 | 30 | 3 (0)| 00:00:01 | | |
|* 9 | table access full | products | 1 | 30 | 3 (0)| 00:00:01 | | |
| 10 | partition range all | | | | | | 1 | 28 |
| 11 | bitmap conversion to rowids | | | | | | | |
| 12 | bitmap and | | | | | | | |
|* 13 | bitmap index single value | sales_prod_bix | | | | | 1 | 28 |
|* 14 | bitmap index single value | sales_channel_bix | | | | | 1 | 28 |
| 15 | table access by local index rowid| sales | 3190 | 63800 | 378 (0)| 00:00:05 | 1 | 1 |
--------------------------------------------------------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - access("s"."cust_id"="c"."cust_id")
plan_table_output
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3 - filter("c"."cust_first_name"='abigail')
7 - filter("ch"."channel_desc"='direct_sales')
9 - filter("p"."prod_name"='y box')
13 - access("s"."prod_id"="p"."prod_id")
14 - access("s"."channel_id"="ch"."channel_id")
32 rows selected.
elapsed: 00:00:00.56
事实表必须有主键或唯一约束,而且主键必须是validated状态的。
将约束的状态改为validated(经过验证的),因为有时候有可能会有不符合的值出现在里面,比如enable novalidate操作后。
sh@ prod1> alter table products modify primary key validate ; table altered. elapsed: 00:00:01.44 sh@ prod1> alter table customers modify primary key validate ; table altered. elapsed: 00:00:00.23 sh@ prod1> alter table channels modify primary key validate ; table altered. elapsed: 00:00:00.23
需要注意的是,索引是建立在谓词列上的,这些列来自扩展后的事实表。
create bitmap index sales_bji1 on sales(p.prod_name , c.cust_first_name , ch.channel_desc ) 2 from sales s , products p , customers c , channels ch 3 where 4 s.prod_id = p.prod_id and 5 s.cust_id = c.cust_id and s.channel_id = ch.channel_id 7 local ; index created. elapsed: 00:01:54.07
重新来看
explain plan for
2 select sum( s.quantity_sold ) , sum( s.amount_sold ) from sales s , products p , customers c , channels ch
where s.prod_id = p.prod_id and s.cust_id = c.cust_id and s.channel_id = ch.channel_id and p.prod_name = 'y box' and
4 c.cust_first_name = 'abigail' and ch.channel_desc = 'direct_sales' ;
explained.
elapsed: 00:00:00.23
sh@ prod1> select * from table(dbms_xplan.display) ;
plan_table_output
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
plan hash value: 1034966156
------------------------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time | pstart| pstop |
------------------------------------------------------------------------------------------------------------------
| 0 | select statement | | 1 | 20 | 61 (0)| 00:00:01 | | |
| 1 | sort aggregate | | 1 | 20 | | | | |
| 2 | partition range all | | 19 | 380 | 61 (0)| 00:00:01 | 1 | 28 |
| 3 | table access by local index rowid| sales | 19 | 380 | 61 (0)| 00:00:01 | 1 | 28 |
| 4 | bitmap conversion to rowids | | | | | | | |
|* 5 | bitmap index single value | sales_bji1 | | | | | 1 | 28 |
------------------------------------------------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
5 - access("s"."sys_nc00008$"='y box' and "s"."sys_nc00009$"='abigail' and
"s"."sys_nc00010$"='direct_sales')
18 rows selected.
elapsed: 00:00:00.29
执行计划得到了极大的简化。