Tuesday, August 3, 2010

Advanced Query Rewrite in 10g

Learnt something new about Oracle Database pretty much every day. Recently I learned something its about advanced query rewrite in 10g EE

scott@ORCL> create table customer
  2  nologging
  3  as
  4  select rownum as cust_id,
  5         object_name as cust_name,
  6         object_type as cust_type,
  7         created  as  created_dt
  8  from all_objects
  9  /

Table created.

Elapsed: 00:00:10.34
scott@ORCL> create table sales
  2  nologging
  3  as
  4  select decode(mod(level,366),0,1) as cust_id,
  5         abs(dbms_random.random)/100 as sales_amt,
  6         trunc(sysdate,'yyyy')+level as trans_date
  7  from dual
  8  connect by level <=100000
  9  /

Table created.

Elapsed: 00:00:01.46
scott@ORCL> alter table customer add constraint cust_pk primary key(cust_id);

Table altered.

Elapsed: 00:00:02.14
scott@ORCL> alter table sales add constraint sales_fk foreign key(cust_id) references customer;

Table altered.

Elapsed: 00:00:00.89
scott@ORCL> begin
  2    dbms_stats.gather_table_stats(ownname=>USER,tabname=>'CUSTOMER',estimate_percent=>100,cascade=>true,method_opt=>'for all indexed columns size 254');
  3    dbms_stats.gather_table_stats(ownname=>USER,tabname=>'SALES',estimate_percent=>100,cascade=>true,method_opt=>'for all indexed columns size 254');
  4  end;
  5  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:08.59
scott@ORCL> create table cust_sales_mv
  2  nologging
  3  as
  4  select c.cust_id,count(s.cust_id) cust_count,sum(s.sales_amt) as sales_amt
  5  from customer c,sales s
  6  where c.cust_id = s.cust_id (+)
  7  and   c.created_dt between to_date('01/01/2005','mm/dd/yyyy') and to_date('12/31/2005','mm/dd/yyyy')
  8  group by c.cust_id
  9  /

Table created.

Elapsed: 00:00:00.06


scott@ORCL> begin
  2     sys.DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE (
  3             name =>'demo_rewrite',
  4             source_stmt => ' select c.cust_id,count(s.cust_id) cust_count,sum(s.sales_amt) as sales_amt '||
  5                                             ' from customer c,sales s '||
  6                                             ' where c.cust_id = s.cust_id (+) '||
  7                                             ' and   c.created_dt between to_date(''01/01/2005'',''mm/dd/yyyy'') and to_date(''12/31/2005'',''mm/dd/yyyy'') ' ||
  8                                             ' group by c.cust_id ' ,
  9             destination_stmt =>' select * from cust_sales_mv ',
 10             validate => false,
 11             rewrite_mode =>'TEXT_MATCH' );
 12  end;
 13  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.76

Now for this Query rewrite to take place ensure that query_rewrite_integrity should be either trusted or stale_tolerated

scott@ORCL> alter session set query_rewrite_integrity=trusted;

Session altered.

Elapsed: 00:00:00.00
scott@ORCL> set autotrace traceonly explain;
scott@ORCL> select c.cust_id,count(s.cust_id) cust_count,sum(s.sales_amt) as sales_amt
  2  from customer c,sales s
  3  where c.cust_id = s.cust_id (+)
  4  and   c.created_dt between to_date('01/01/2005','mm/dd/yyyy') and to_date('12/31/2005','mm/dd/yyyy')
  5  group by c.cust_id;
Elapsed: 00:00:00.85

Execution Plan
----------------------------------------------------------
Plan hash value: 2300330077

-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               |     1 |    39 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| CUST_SALES_MV |     1 |    39 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

scott@ORCL> set autotrace off;

No comments:

Post a Comment