Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> materialized view refresh in 9i vs. 10g
In the process of migrating a database from Oracle 9.0 to 10.2, I came
across a mundane-looking mview that refreshes quickly on the old 9i
database but never finishes a complete-mode refresh under 10g. It
turns out that in Oracle 9.0 and 9.2, "dbms_mview.refresh(mview_name,
'C')" uses TRUNCATE and direct-path insert, but under 10.2 it uses
DELETE and conventional-path INSERT. The latter approach has the merit
of not implicitly committing the underlying table in an empty state
(via the truncate), but it costs a great deal more in undo and redo
space (and also potentially in runtime). The cost is much higher if
the mview has indexes, as mine does.
Does anyone know why the behavior of refresh changed and if there's a way to invoke the truncate/append logic (other than writing a home-grown refresh procedure)?
Test cases follow:
SQL> create table t as select object_id from all_objects where rownum
<= 30000 ;
SQL> alter table t add constraint pk_t primary key ( object_id ) ;
SQL> create materialized view t_mv as select object_id from t ;
SQL> column value new_val V SQL> set verify off SQL> column name format a15 SQL> select name, value
NAME VALUE --------------- ---------- redo size 1850568
SQL> alter session set events '10046 trace name context forever, level
12' ;
SQL> exec dbms_mview.refresh('T_MV', 'C') ;
Elapsed: 00:00:00.36
SQL> select name, value, to_char(value-&V, '999,999,999') as diff
from v$statname join v$mystat using (statistic#)
where name = 'redo size'
;
NAME VALUE DIFF --------------- ---------- ------------ redo size 3928916 2,078,348
% less tkprof.out
//////////////////////////////////////////////////////////////////////////////////// /// Start of trace file excerpts /// ////////////////////////////////////////////////////////////////////////////////////truncate table "FOO"."T_MV" purge snapshot log
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 1 0 Execute 1 0.02 0.08 7 39 35 0 Fetch 0 0.00 0.00 0 0 0 0
total 2 0.02 0.08 7 39 36 0
...
INSERT /*+ APPEND */ INTO "FOO"."T_MV"("OBJECT_ID") SELECT
"T"."OBJECT_ID"
FROM "T" "T"
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.00 0 0 0 0 Execute 1 0.23 0.29 2 183 1337 30000 Fetch 0 0.00 0.00 0 0 0 0
30000
//////////////////////////////////////////////////////////////////////////////////// /// End of trace file excerpts /// //////////////////////////////////////////////////////////////////////////////////// =============================================Case 2: Oracle 10.2.0.1.0 - Standard Edition
SQL> create table t as select object_id from all_objects where rownum
<= 30000 ;
SQL> alter table t add constraint pk_t primary key ( object_id ) ;
SQL> create materialized view t_mv as select object_id from t ;
SQL> column value new_val V SQL> set verify off SQL> column name format a15 SQL> select name, value from v$statname join v$mystat using(statistic#) where name = 'redo size' ;
NAME VALUE --------------- ---------- redo size 1847556
SQL> exec dbms_monitor.session_trace_enable(); SQL> exec dbms_mview.refresh('T_MV', 'C') ;
Elapsed: 00:00:02.23
SQL> select name, value, to_char(value-&V, '999,999,999') as diff
from v$statname join v$mystat using (statistic#)
where name = 'redo size'
;
NAME VALUE DIFF --------------- ---------- ------------ redo size 22864832 21,017,276
% less tkprof.out
//////////////////////////////////////////////////////////////////////////////////// /// Start of trace file excerpts /// ////////////////////////////////////////////////////////////////////////////////////delete from "FOO"."T_MV"
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 2 0 0 Execute 1 1.87 1.82 62 48 91854 30000 Fetch 0 0.00 0.00 0 0 0 0
30000
Event waited on Times Max. Wait TotalWaited
...
INSERT /*+ BYPASS_RECURSIVE_CHECK */ INTO "FOO"."T_MV"("OBJECT_ID")
SELECT
"T"."OBJECT_ID" FROM "T" "T"
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 2 0 0 Execute 1 0.53 0.52 0 180 61404 30000 Fetch 0 0.00 0.00 0 0 0 0
30000
(No wait events.)
//////////////////////////////////////////////////////////////////////////////////// /// End of trace file excerpts /// //////////////////////////////////////////////////////////////////////////////////// ================================================================Case 3: Manually truncate and then refresh in Oracle 10.2.0.1.0
SQL> column value new_val V SQL> set verify off SQL> col name format a15 SQL> select name, value from v$statname join v$mystat using(statistic#) where name = 'redo size' ;
NAME VALUE --------------- ---------- redo size 0
SQL> truncate table t_mv ;
SQL> select name, value, to_char(value-&V, '999,999,999') as diff
from v$statname join v$mystat using (statistic#)
where name = 'redo size'
;
NAME VALUE DIFF --------------- ---------- ------------ redo size 20032 20,032
SQL> exec dbms_mview.refresh('T_MV', 'C') ;
SQL> select name, value, to_char(value-&V, '999,999,999') as diff
from v$statname join v$mystat using (statistic#)
where name = 'redo size'
;
NAME VALUE DIFF --------------- ---------- ------------ redo size 7140452 7,120,420Received on Sun Jun 11 2006 - 00:58:54 CDT