Materialized Views

REFRESH FAST
Now that we know how materialized view logs track changes to base tables we can use them to perform fast materialized view refreshes, i.e. refreshes where only the individual materialized view rows affected by base table changes are updated. This is also called "incremental" refreshing. Earlier in this tutorial we saw how the rowids for each row in a materialized view changed after a complete refresh. Now let's see what happens to a materialized view's rowids after a fast refresh. First we use the REFRESH FAST clause to specify that the default refresh method should be fast.
create materialized view log on t with sequence ;

create materialized view mv REFRESH FAST as select * from t ;

select key, val, rowid from mv ;

KEY VAL

ROWID

---------- ----- -----------------1 a 2 b 3 c 4 AAAWm+AAEAAAAaMAAA AAAWm+AAEAAAAaMAAB AAAWm+AAEAAAAaMAAC AAAWm+AAEAAAAaMAAD

Now we refresh the materialized view. The "F" value for the "method" parameter ensures the refresh will be a Fast one.
execute dbms_mview.refresh( list => 'MV', method => 'F' );

select key, val, rowid from mv ;

KEY VAL

ROWID

---------- ----- -----------------1 a 2 b 3 c 4 AAAWm+AAEAAAAaMAAA AAAWm+AAEAAAAaMAAB AAAWm+AAEAAAAaMAAC AAAWm+AAEAAAAaMAAD

The rowids did not change. Thus, with a fast refresh the materialized view data is not touched when no changes have been made to the base table, unlike a complete refresh where each row would have been created anew. Now let's update a row in the base table.
update t set val = 'XX' where key = 3 ;

commit;

execute dbms_mview.refresh( list => 'MV', method => 'F' );

select key, val, rowid from mv ;

KEY VAL

ROWID

---------- ----- -----------------1 a 2 b 3 XX 4 AAAWm+AAEAAAAaMAAA AAAWm+AAEAAAAaMAAB AAAWm+AAEAAAAaMAAC AAAWm+AAEAAAAaMAAD

Still no change in the rowids. In row 3 we can see that VAL changed from "c" to "XX" though, telling us that row 3 was updated during the refresh. Defaults The REFRESH FAST clause of the CREATE MATERIALIZED VIEW command tells Oracle what type of refresh to perform when no refresh option is specified. A materialized view created with REFRESH FAST can still be refreshed completely if required though. In the following example note how, even though MV was created above with the REFRESH FAST clause, all its rowids change after the refresh. This indicates that a complete refresh was performed.
execute dbms_mview.refresh( list => 'MV', method => 'C' );

select key, val, rowid from mv ;

-----------------1 a 2 b 3 XX AAAWnBAAEAAAAaMAAA AAAWnBAAEAAAAaMAAB AAAWnBAAEAAAAaMAAC . drop materialized view mv . select key. KEY VAL ROWID ---------.-----------------1 a 2 b 3 XX 4 AAAWm+AAEAAAAaMAAE AAAWm+AAEAAAAaMAAF AAAWm+AAEAAAAaMAAG AAAWm+AAEAAAAaMAAH Similarly a materialized view created with REFRESH COMPLETE can be fast refreshed (assuming the materialized view is capable of being fast refreshed.----.----. create materialized view mv REFRESH COMPLETE as select * from t . val. rowid from mv .KEY VAL ROWID ---------. we'll learn more about this later).

val. update t set val = 'c' where key = 3 . KEY VAL ROWID ---------.4 AAAWnBAAEAAAAaMAAD execute dbms_mview. Materialized Views . indicating a fast refresh. drop materialized view log on t . select key.----.refresh( list => 'MV'. Cleanup drop materialized view mv . rowid from mv . method => 'F' ). commit .-----------------1 a 2 b 3 XX 4 AAAWnBAAEAAAAaMAAA AAAWnBAAEAAAAaMAAB AAAWnBAAEAAAAaMAAC AAAWnBAAEAAAAaMAAD Note how none of the rowids in MV changed.

'e' ) . select count(*) from mlog$_t . COUNT(*) ---------1 . commit. create materialized view mv refresh fast as select * from t .Purging Materialized View Logs Oracle automatically purges rows in the materialized view log when they are no longer needed. create materialized view log on t . In the example below note how the log table is empty after the refresh. select count(*) from mlog$_t . COUNT(*) ---------0 insert into t values ( 5.

PURGE_LOG If a materialized view log needs to be purged manually for some reason a procedure called DBMS_MVEW. method => 'F' ).execute dbms_mview. COUNT(*) ---------0 update t set val = 'X' where key = 5 . select count(*) from mlog$_t . select count(*) from mlog$_t . COUNT(*) ---------1 .PURGE_LOG can be used. COUNT(*) ---------0 DBMS_MVEW.refresh( list => 'MV'. commit. select count(*) from mlog$_t .

execute DBMS_MVIEW.PURGE_LOG( master => 'T', num => 9999, flag => 'delete' ) ;

select count(*) from mlog$_t ;

COUNT(*) ---------0

The "num" and "flag" parameters can be used to partially purge the log. See the PURGE_LOG manual page for further details. Once a materialized view log has been purged any materialized views dependent on the deleted rows cannot be fast refreshed. Attempting a fast refresh will raise an error.
execute dbms_mview.refresh( list => 'MV', method => 'F' ); BEGIN dbms_mview.refresh( list => 'MV', method => 'F' ); END;

* ERROR at line 1: ORA-12034: materialized view log on "SCOTT"."T" younger than last refresh ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2537 ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2743 ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2712 ORA-06512: at line 1

Such materialized views will need to be refreshed completely.
select * from mv ;

KEY VAL ---------- ----1 a 2 b 3 c 4 5 e

execute dbms_mview.refresh( list => 'MV', method => 'C' );

select * from mv ;

KEY VAL ---------- ----1 a 2 b 3 c 4 5 X

Cleanup
delete from t where key = 5 ; commit;

drop materialized view mv ;

drop materialized view log on t ;

Materialized Views
REFRESH FAST Categories
There are three ways to categorize a materialized view's ability to be fast refreshed. 1. It can never be fast refreshed. 2. It can always be fast refreshed. 3. It can be fast refreshed after certain kinds of changes to the base table but not others. For the first case Oracle will raise an error if you try to create such a materialized view with its refresh method defaulted to REFRESH FAST. In the example below table T does not have a materialized view log on it. Materialized views based on T cannot therefore be fast refreshed. If we attempt to create such a materialized view we get an error.
create materialized view MV REFRESH FAST as select * from t2 ; as select * from t2

---------. The next example demonstrates why. .---------10 20 30 40 50 1 1 1 2 2 100 300 200 250 150 create materialized view log on t2 with primary key. The third case is a little trickier. and will always be fast refreshed unless a complete refresh is explicitly requested. select * from t2 .* ERROR at line 3: ORA-23413: table "SCOTT". sequence ( t_key. amt ) including new values . rowid. obviously. KEY T_KEY AMT ---------."T2" does not have a materialized view log For the second case materialized views are created without error.

method => 'F' ). .---------AAAhMzAAEAAAEG8AAA AAAhMzAAEAAAEG8AAB 1 2 300 250 So far everything works as expected. max( amt ) amt_max from t2 group by t_key .refresh( list => 'MV'.create materialized view mv REFRESH FAST as select t_key. commit. select rowid. t_key. execute dbms_mview. amt_max from mv . 2. 500 ).---------. ROWID T_KEY AMT_MAX -----------------. t_key. insert into t2 values ( 5. Let's try inserting a row into the base table. select rowid. amt_max from mv . We created a materialized view log and created a materialized view with fast refresh as its default refresh method.

line 2255 ORA-06512: at "SYS.DBMS_SNAPSHOT". END. execute dbms_mview.REFRESH command) and the materialized view correctly shows 500 as the maximum value for rows with T_KEY = 2. it worked as expected.DBMS_SNAPSHOT". BEGIN dbms_mview.refresh( list => 'MV'. commit.---------AAAhMzAAEAAAEG8AAA AAAhMzAAEAAAEG8AAB 1 2 300 500 Again. line 2430 ORA-06512: at line 1 . delete from t2 where key = 5 .refresh( list => 'MV'.ROWID T_KEY AMT_MAX -----------------. * ERROR at line 1: ORA-32314: REFRESH FAST of "SCOTT".DBMS_SNAPSHOT". method => 'F' )."MV" unsupported after deletes/updates ORA-06512: at "SYS. Now let's try deleting a row from the base table. The view was fast refreshed (the rowid's did not change after the DBMS_MVIEW. method => 'F' ). line 2461 ORA-06512: at "SYS.---------.

---------. sometimes. In general materialized views cannot be fast refreshed if the base tables do not have materialized view logs or the defining query:          contains an analytic function contains non-repeating expressions like SYSDATE or ROWNUM contains RAW or LONG RAW data types contains a subquery in the SELECT clause contains a MODEL clause contains a HAVING clause contains nested queries with ANY. Here are some of them. method => 'C' ).refresh( list => 'MV'. amt_max from mv . select rowid. DBMS_MVIEW.This time we received an error when we attempted a fast refresh. not updates or deletes. or NOT EXISTS contains a CONNECT BY clause references remote tables in different databases . execute dbms_mview.) To synchronize an insert-only materialized view after a delete we need to do a complete refresh.EXPLAIN_MVIEW. ALL. The reason is because this type of materialized view is an "insert-only" materialized view. ROWID T_KEY AMT_MAX -----------------. t_key.e. i.---------AAAhMzAAEAAAEG8AAC AAAhMzAAEAAAEG8AAD 1 2 300 250 Restrictions on Fast Refresh So how do we know whether a materialized view can be fast refreshed each time. it is only fast refreshable for inserts and direct loads. (We will see why it is an insert-only view in the next topic. or never? One way would be to learn all the documented restrictions for fast refreshable materialized views.

predicting whether or not a materialized view is fast refreshable can be complicated. The following links can help you find them if required though.EXPLAIN_MVIEW utility can simplify this task however. subqueries. The material below will help you use the utility effectively. UNION ALL. Full details on how the utility works are available at the preceding link. etc. drop materialized view log on t2 . aggregates.  Cleanup drop materialized view mv . It uses the DBMS_MVIEW. simpler alternative for determining whether a materialized view is fast refreshable or not. They are documented in various sections of a few different manuals and are too numerous and complex to repeat here.  CREATE MATERIALIZED VIEW . TheDBMS_MVIEW. There are even more restrictions for materialized views containing joins. . Materialized Views DBMS_MVIEW.EXPLAIN_MVIEW utility which we will explore next.references remote tables in a single database and defaults to the ON COMMIT refresh mode  references other materialized views which are not join or aggregate materialized views.EXPLAIN_MVIEW As we saw in the preceding topic.FAST Clause  General Restrictions on Fast Refresh  Restrictions on Fast Refresh on Materialized Views with Joins Only  Restrictions on Fast Refresh on Materialized Views with Aggregates  Restrictions on Fast Refresh on Materialized Views with UNION ALL  Restrictions for Materialized Views with Subqueries  Restrictions for Materialized Views with Unions Containing Subqueries  Restrictions for Using Multitier Materialized Views  Restrictions for Materialized Views with Collection Columns Fortunately there is a second.

EXPLAIN_MVIEW. create table MV_CAPABILITIES_TABLE ( statement_id mvowner mvname capability_name possible related_text related_num msgno msgtxt seq ) . integer . via a table or via a varray. documented CREATE TABLE command for MV_CAPABILITIES_TABLE can be found on UNIX systems at $ORACLE_HOME/rdbms/admin/utlxmv.Using MV_CAPABILITIES_TABLE (see Gotchafor a related bug). varchar(30) . varchar(2000) .EXPLAIN_MVIEW with the table output method typically involves . varchar(2000) .MV_CAPABILITIES_TABLE There are two ways to get the output from DBMS_MVIEW. number VARRAY Output Using DBMS_MVIEW.Basic Materialized Views . varchar(30) . number . varchar(30) . The full. To use the table method the current schema must contain a table called MV_CAPABILITIES_TABLE. It is also available in Oracle's documentation at Oracle Database Data Warehousing Guide .sql. Here is an abridged version. character(1) . varchar(30) .

EXPLAIN_MVIEW's "mv" parameter o it can contain either a query. varchar2 default 'N' . CREATE MATERIALIZED VIEW command text. number default 80 p_include_pct_capabilities in p_linesize ) return clob as in --------------------------------------------------------------------------------. running DBMS_MVIEW.EXPLAIN_MVIEW 3.html --. or the default p_mv o this value is passed to DBMS_MVIEW. create or replace function my_mv_capabilities ( p_mv p_capability_name_filter in in varchar2 .sqlsnippets. deleting old rows from MV_CAPABILITIES_TABLE 2. varchar2 default '%' .From http://www.Parameters: --------p_capability_name_filter o use either REFRESH. or a materialized view name . REWRITE.EXPLAIN_MVIEW's varray output option instead and supplement it with a custom function called MY_MV_CAPABILITIES. selecting new rows from MV_CAPABILITIES_TABLE.com/en/topic-12884. PCT. To save time in this tutorial we will use DBMS_MVIEW.1.

capabilities like REFRESH_FAST_PCT are not included in the report pragma autonomous_transaction .----------. p_linesize o the maximum size allowed for any line in the report output o data that is longer than this value will be word wrapped p_include_pct_capabilities Y .Typical Usage: --------------------------------------------------------------------------------------o the value 5000 is arbitraty. v_nl constant char(1) := unistr( '\000A' ). any value big enough to contain the report output will do set long 5000 select my_mv_capabilities( 'MV_NAME' ) as mv_report from dual .new line v_previous_possible char(1) := 'X' . -. .capabilities like REFRESH_FAST_PCT are included in the report N .

. related_text . msg_array => v_capabilities ) . v_output clob . possible .v_capabilities sys.explain_mview( mv => p_mv. begin dbms_mview. msgtxt from table( v_capabilities ) where capability_name like '%' || upper( p_capability_name_filter ) || '%' and not ( capability_name like '%PCT%' and upper(p_include_pct_capabilities) = 'N' ) order by mvowner . for v_capability in ( select capability_name .ExplainMVArrayType .

print section heading ------------------------------------------------------------ if v_capability. possible desc .possible <> v_previous_possible then v_output := v_output || v_nl || case v_capability. .mvname .possible || ':' end || v_nl . seq ) loop ------------------------------------------------------------.possible when 'T' then 'Capable of: ' when 'Y' then 'Capable of: ' when 'F' then 'Not Capable of: ' when 'N' then 'Not Capable of: ' else v_capability.

------------------------------------------------------------.end if.capability_name || v_nl .5 ).print related text indented 4 spaces and word wrapped . begin -.print capability name indented 2 spaces v_output := v_output || v_nl || ' ' || v_capability. v_previous_possible := v_capability. -.possible .print section body -----------------------------------------------------------declare v_indented_line_size varchar2(3) := to_char( p_linesize .

' ) .related_text || ' ' . '(.msgtxt || ' ' .print message text indented 4 spaces and word wrapped if v_capability.msgtxt is not null then v_output := v_output || regexp_replace ( v_capability.' || v_indented_line_size || '} |. -. \1' || v_nl end if.related_text is not null then v_output := v_output || regexp_replace ( v_capability.' || v_indented_line_size || '})' .' .{1. '(.{1.if v_capability.{1.{1.' || v_indented_line_size || '} |.

end.|| v_indented_line_size || '})' . end. commit . ' ) . / show errors No errors. This completes our preparations. end loop.EXPLAIN_MVIEW With a Query . \1' || v_nl end if. DBMS_MVIEW.EXPLAIN_VIEW in action. return( v_output ). Now let's see DBMS_MVIEW.

T the detail table does not have a materialized view log .DBMS_MVIEW. Here is an example that explains a simple query which could appear as the defining query in a CREATE MATERIALIZED VIEW command. an existing materialized view. MV_REPORT -------------------------------------------------------------------------------- Capable of: REFRESH_COMPLETE Not Capable of: REFRESH_FAST REFRESH_FAST_AFTER_INSERT SCOTT. a CREATE MATERIALIZED VIEW command 3.EXPLAIN_MVIEW can analyze three different types of materialized view code: 1. 'REFRESH' ) as mv_report from dual . a defining query 2. set long 5000 select my_mv_capabilities( 'SELECT * FROM T'.

REFRESH_FAST_AFTER_ONETAB_DML see the reason why REFRESH_FAST_AFTER_INSERT is disabled REFRESH_FAST_AFTER_ANY_DML see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled (Descriptions of each capability name are available at Table 8-7 CAPABILITY_NAME Column Details.EXPLAIN_MVIEW can report on a materialized view's refresh. Note that DBMS_MVIEW. For now we will only examine refresh capabilities. 'REFRESH' ) as mv_report from dual . select my_mv_capabilities ( 'CREATE MATERIALIZED VIEW MV REFRESH FAST AS SELECT * FROM T' . DBMS_MVIEW. rewrite.EXPLAIN_MVIEW With CREATE MATERIALIZED VIEW Now let's create a materialized view log on T and then use EXPLAIN_MVIEW to explain the capabilities of an entire CREATE MATERIALIZED VIEW command. create materialized view log on t . . Rewrite capabilities will be covered in Query Rewrite Restrictions and Capabilities. A list of messages and related text is available at Table 8-8 MV_CAPABILITIES_TABLE Column Details. and partition change tracking (PCT) capabilities.) The EXPLAIN_MVIEW output above shows that fast refresh is not possible in this case because T has no materialized view log.

amt ) including new values . rowid. DBMS_MVIEW. the insertonly one we saw in the preceding topic REFRESH FAST Categories. sequence ( t_key. create materialized view log on t2 with primary key.MV_REPORT -------------------------------------------------------------------------------- Capable of: REFRESH_COMPLETE REFRESH_FAST REFRESH_FAST_AFTER_INSERT REFRESH_FAST_AFTER_ONETAB_DML REFRESH_FAST_AFTER_ANY_DML This time we see that a materialized view using our simple query could be fast refreshable in all cases.EXPLAIN_MVIEW With Existing Materialized View For our last example we will explain an existing materialized view.

MV_REPORT -------------------------------------------------------------------------------- Capable of: REFRESH_COMPLETE REFRESH_FAST REFRESH_FAST_AFTER_INSERT Not Capable of: . create materialized view mv refresh fast as select t_key. max( amt ) amt_max from t2 group by t_key .. select my_mv_capabilities( 'MV'. 'REFRESH' ) as mv_report from dual .

Note also that the "REFRESH_FAST" capability will appear whenever at least one of the other REFRESH_FAST_% capabilities is available.Basic Materialized Views .sql file and the CREATE TABLE command at Oracle Database Data Warehousing Guide . delete from mv_capabilities_table ...F = capability is not possible .. Gotcha Both the $ORACLE_HOME/rdbms/admin/utlxmv. but not other types of DML. CREATE TABLE MV_CAPABILITIES_TABLE . It does not mean the materialized view is fast refreshable in all cases.POSSIBLE will either be "T" or "F". -.Using MV_CAPABILITIES_TABLE state the values in MV_CAPABILITIES_TABLE.T = capability is possible -.. In actual use we can see the values are really "Y" and "N". . POSSIBLE CHARACTER(1).REFRESH_FAST_AFTER_ONETAB_DML mv uses the MIN or MAX aggregate functions REFRESH_FAST_AFTER_ONETAB_DML COUNT(*) is not present in the select list REFRESH_FAST_AFTER_ANY_DML see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled Here we see that fast refresh is available after inserts.

column possible format a8 select distinct POSSIBLE from mv_capabilities_table .execute dbms_mview. . used when DBMS_MVIEW. drop materialized view log on t2 . commit. POSSIBLE -------Y N The values "T" and "F" are.EXPLAIN_MVIEW output is saved to a varray. drop materialized view log on t . however. Cleanup set long 80 drop materialized view mv .explain_mview( 'select * from t' ).

create materialized view log on t2 with primary key. rowid. max( amt ) amt_max from t2 group by t_key . select rowid.Materialized Views REFRESH FORCE In REFRESH FAST Categories and DBMS_MVIEW. ROWID T_KEY AMT_MAX -----------------. With these types of materialized views it is often most convenient to let Oracle decide which refresh method is best. amt_max from mv . It performs a FAST refresh if possible. t_key.---------- . create materialized view mv REFRESH FORCE as select t_key. sequence ( t_key.EXPLAIN_MVIEW we saw an insert-only materialized view which could be fast refreshed after inserts into the base table but needed a complete refresh after other types of DML.---------. The REFRESH FORCE method does just that. otherwise it performs a COMPLETE refresh. amt ) including new values .

execute dbms_mview.AAAWpLAAEAAAAaMAAA AAAWpLAAEAAAAaMAAB 1 2 300 250 First let's try an insert and a refresh. 500 ).refresh( list => 'MV' ).refresh( list => 'MV' ). t_key. execute dbms_mview. commit.---------AAAWpLAAEAAAAaMAAA AAAWpLAAEAAAAaMAAB 1 2 300 500 Since the rowids did not change but the AMT_MAX values did we can tell that a FAST refresh was performed. select rowid. insert into t2 values ( 5. t_key. amt_max from mv .---------. Now let's try a delete followed by a refresh. ROWID T_KEY AMT_MAX -----------------. commit. delete from t2 where key = 5 . 2. amt_max from mv . . select rowid.

drop materialized view log on t2 . Materialized Views NEVER REFRESH If for some reason we need to prevent refresh operations of any sort."MV" unsupported after deletes/updates" error at this point. on our materialized views we can use theNEVER REFRESH method. Instead Oracle performed a COMPLETE refresh (note how the rowids for each row changed).---------. This time with REFRESH FORCE we did not.ROWID T_KEY AMT_MAX -----------------.---------AAAWpLAAEAAAAaMAAC AAAWpLAAEAAAAaMAAD 1 2 300 250 In the REFRESH FAST Categories topic we received an "ORA-32314: REFRESH FAST of "SCOTT". FAST or COMPLETE. create materialized view mv NEVER REFRESH as select * from t . Cleanup drop materialized view mv .

BEGIN dbms_mview. commit .DBMS_SNAPSHOT".. select * from mv .refresh( 'MV' ). line 2743 . update t set val = upper(val) . * ERROR at line 1: ORA-23538: cannot explicitly refresh a NEVER REFRESH materialized view ("MV") ORA-06512: at "SYS. KEY VAL ---------.----1 a 2 b 3 c 4 Let's see what happens when we update the base table and then attempt a refresh. END.DBMS_SNAPSHOT". line 2537 ORA-06512: at "SYS.refresh( 'MV' ). execute dbms_mview.

line 2712 ORA-06512: at line 1 Oracle prevented the refresh by raising an error.ORA-06512: at "SYS.REFRESH command. (If you know of any please let me know using the Comments link below. I cannot see a practical reason for having a materialized view with NEVER REFRESH set at all times. In other words this . Materialized Views ON DEMAND Up to this point in the tutorial we have always refreshed our materialized views manually with the DBMS_MVIEW. This is know as ON DEMAND refreshing and it is the default refresh mode when none is specified in the CREATE MATERIALIZED VIEW command. commit . In this case the materialized view's refresh mode can be changed to NEVER REFRESH using the ALTER MATERIALIZED VIEW command. Cleanup drop materialized view mv .DBMS_SNAPSHOT".) NEVER REFRESH can come in handy though when refresh operations on a materialized view need to be prevented temporarily during maintenance or debugging operations. update t set val = lower(val) .

REFRESH.REFRESH_DEPENDENT Here is an example that uses DBMS_MVIEW. To refresh ON DEMAND materialized views we explicitly call one of the following procedures. create materialized view mv REFRESH ON DEMAND as select * from t . no rows selected .REFRESH  DBMS_MVIEW. drop materialized view mv . DBMS_MVIEW. is equivalent to this.create materialized view mv as select * from t .  insert into t values ( 5.REFRESH_ALL_MVIEWS  DBMS_MVIEW. commit. 'e' ). select * from mv where key = 5 .

KEY VAL ---------.REFRESH( 'MV' ). create materialized view log on t . select * from mv where key = 5 . This is possible using the ON COMMIT refresh mode. .execute DBMS_MVIEW. Here is an example. delete from t where key = 5 .----5 e Cleanup drop materialized view mv . Materialized Views ON COMMIT In some situations it would be convenient to have Oracle refresh a materialized view automatically whenever changes to the base table are committed. commit.

select rowid. val from mv .---------. ROWID KEY VAL -----------------. 'e' ).---------.----AAAXNGAAEAAAAasAAA AAAXNGAAEAAAAasAAB AAAXNGAAEAAAAasAAC AAAXNGAAEAAAAasAAD 1 a 2 b 3 c 4 Let's see what happens to the view in the course of an insert operation. key. key.create materialized view mv REFRESH FAST ON COMMIT as select * from t . val from mv . insert into t values ( 5. ROWID KEY VAL -----------------.----AAAXNGAAEAAAAasAAA AAAXNGAAEAAAAasAAB 1 a 2 b . select rowid.

. Restrictions Materialized views can only refresh ON COMMIT in certain situations.AAAXNGAAEAAAAasAAC AAAXNGAAEAAAAasAAD 3 c 4 Nothing happend yet. select rowid. The base tables will never have any distributed transactions applied to them. The materialized view cannot contain object types or Oracle-supplied types. No call to DBMS_MVIEW. The first case produces an error during the CREATE MATERIALIZED VIEW command. key.----AAAXNGAAEAAAAasAAA AAAXNGAAEAAAAasAAB AAAXNGAAEAAAAasAAC AAAXNGAAEAAAAasAAD AAAXNGAAEAAAAatAAA 1 a 2 b 3 c 4 5 e Note how the materialized view was automatically fast refreshed after the COMMIT command. 1.REFRESH was required. ROWID KEY VAL -----------------.---------. Let's issue a COMMIT. val from mv . 2. commit.

In the following example materialized view MV (created at the top of this page) was created with REFRESH FAST. will therefore raise an error. sys_xmlgen( val ) as val_xml from t .because the materialized view contains an Oracle-supplied type create materialized view mv2 REFRESH FAST ON COMMIT as select key. insert into t select key+10.-. val. as select key. some remote DBs may be in-doubt ORA-02051: another session in same transaction failed . val from T@REMOTE . sys_xmlgen( val ) as val_xml from t * ERROR at line 3: ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view The second case generates an error when a distributed transaction is attempted on the base table. commit * ERROR at line 1: ORA-02050: transaction 5. commit. val.this materialized view is not fast refreshable -. Attempting a distributed transaction on its base table.5632 rolled back.21. T.

----1 a 2 b 3 c 4 5 e 11 a 12 b 13 c 14 15 e . select * from t . commit. insert into t select key+10. as the following snippet demonstrates. val from T@REMOTE .) ON DEMAND materialized views have no such restriction. alter materialized view mv refresh ON DEMAND . KEY VAL ---------.(REMOTE is a database link which loops back to the current account.

commit . . val from t . As we can see the CREATE MATERIALZIED view command succeeded even though COMPLETE. not FAST. I also assumed that specifying "REFRESH ON COMMIT" is equivalent to specifying "REFRESH FAST ON COMMIT". create materialized view mv2 REFRESH COMPLETE ON COMMIT as select key.Oracle® Database SQL Language Reference: CREATE MATERIALIZED VIEW When I first read this I assumed it meant that "REFRESH COMPLETE ON COMMIT" is not allowed. was specified with ON COMMIT.cleanup test data in preparation for next section delete from t where key >= 5 .-. "Specify ON COMMIT to indicate that a fast refresh is to occur whenever the database commits a transaction that operates on a master table of the materialized view." -. The next example examines the behavior of "REFRESH ON COMMIT" without a specified refresh method. The following examples prove neither is correct however. Gotcha The SQL Language Reference manual says this about the ON COMMIT clause.

create materialized view mv2 REFRESH ON COMMIT as select key. ROWID KEY VAL -----------------. key.drop materialized view log on t . commit . select rowid. val from t .because it has no materialized view log drop materialized view mv2 . . -. key. select rowid. 'e' ).----AAAXNMAAEAAAAakAAA AAAXNMAAEAAAAakAAB AAAXNMAAEAAAAakAAC AAAXNMAAEAAAAakAAD 1 a 2 b 3 c 4 insert into t values ( 5. val from mv2 .---------.fast refreshable materialized views on T can no longer be created on T -. val from mv2 .

----AAAXNMAAEAAAAakAAE AAAXNMAAEAAAAakAAF AAAXNMAAEAAAAakAAG AAAXNMAAEAAAAakAAH AAAXNMAAEAAAAakAAI 1 a 2 b 3 c 4 5 e The fact that all the rowid's in MV2 changed after the INSERT transaction committed confirms that a complete refresh took place during the commit. delete from t where key >= 5 .ROWID KEY VAL -----------------. Cleanup drop materialized view mv . In fact. drop materialized view mv2 . commit . . Given these observations I can only conclude the documentation is either in error or misleading when it says "specify ON COMMIT to indicate that a fast refresh is to occur". "REFRESH ON COMMIT" is not therefore equivalent to "REFRESH FAST ON COMMIT".---------. when no REFRESH method is specified the default behaviour is "REFRESH FORCE" regardless of whether ON COMMIT is used or not.

the table containing the results of the query. val from t . . which is part of the materialized view also called "MV". column constraint_name format a20 column constraint_type format a15 column index_name format a15 select constraint_name. not to be confused with a base table). index_name from where user_constraints TABLE_NAME = 'MV' .--------------.--------------SYS_C0019948 P SYS_C0019948 In the next example Oracle automatically adds a check constraint. CONSTRAINT_NAME CONSTRAINT_TYPE INDEX_NAME -------------------.e. create materialized view mv as select key. constraint_type.Materialized Views Constraints System Generated Constraints When a materialized view is created Oracle may add system generated constraints to its underlying table (i. In the following example note how Oracle automatically adds a primary key constraint to the table called "MV".

describe t2 Name Null? Type -------------------------------------------. rowid. create materialized view mv refresh fast on commit as select t_key. sequence ( t_key.-----------------------------KEY T_KEY AMT NOT NULL NUMBER NOT NULL NUMBER NOT NULL NUMBER create materialized view log on t2 with primary key. count(*) row_count from t2 group by t_key . amt ) including new values .drop materialized view mv .-------. column search_condition format a30 .

---------. select * from t2 . CONSTRAINT_NAME CONSTRAINT_TYPE SEARCH_CONDITION -------------------.note we used "alter table" here .--------------. When the materialized view is in ON COMMIT mode these constraints effectively constrain the materialized view's base tables.-----------------------------SYS_C0019949 C "T_KEY" IS NOT NULL Adding Your Own Constraints If necessary we can create our own constraints on materialized view tables in addition to the ones Oracle may add. search_condition from where user_constraints table_name = 'MV' .---------10 20 30 40 50 1 1 1 2 2 100 300 200 250 150 alter table mv -.select constraint_name. KEY T_KEY AMT ---------. constraint_type. Let's see this in action by creating a check constraint on MV.

constraint_type.-----------------------------SYS_C0019949 MY_CONSTRAINT C C "T_KEY" IS NOT NULL ROW_COUNT <= 3 Now any attempt to create more than 3 rows per group in table T2 will generate an error at commit time. commit. 500 ). search_condition from where user_constraints table_name = 'MV' . select constraint_name. commit * ERROR at line 1: ORA-12008: error in materialized view refresh path ORA-02290: check constraint (SCOTT. 1.MY_CONSTRAINT) violated . CONSTRAINT_NAME CONSTRAINT_TYPE SEARCH_CONDITION -------------------. insert into T2 values ( 5.add CONSTRAINT MY_CONSTRAINT CHECK ( ROW_COUNT <= 3 ) DEFERRABLE .--------------.

With materialized views they are declared using a few lines of code and are virtually bullet proof when applied correctly. Until the documentation says this is legal it is best to use ALTER TABLE. constraint_type. ALTER MATERIALIZED VIEW mv add constraint my_second_constraint check ( row_count < 4 ) deferrable . select constraint_name.-----------------------------SYS_C0019949 MY_CONSTRAINT C C "T_KEY" IS NOT NULL ROW_COUNT <= 3 row_count < 4 MY_SECOND_CONSTRAINT C The Oracle manual page for ALTER MATERIALIZED VIEW however does not indicate that constraints can be added this way.--------------. Implementing them using triggers can be difficult if not impossible. search_condition from where user_constraints table_name = 'MV' . We will learn more about this powerful multirow validation approach in a future SQL Snippets tutorial so stay tuned! In the mean time Ask Tom "Declarative Integrity" has some good information on the subject. Curiously enough an ALTER MATERIALIZED VIEW command would have worked too. CONSTRAINT_NAME CONSTRAINT_TYPE SEARCH_CONDITION -------------------. . Gotcha When we created MY_CONSTRAINT above we use an ALTER TABLE command.Implementing multirow validation rules such as this one properly is not possible using check constraints on regular tables.

drop materialized view log on t2 . the table containing the results of the query. Materialized Views Indexes When a materialized view is created Oracle may add system generated indexes to its underlying table (i. create materialized view mv as select key. column index_name format a15 column column_name format a15 select index_name . val from t .Cleanup drop materialized view mv .column_name from user_indexes i . In the following example note how Oracle automatically adds an index to implement the system generated primary key we saw in the preceding topic. ic.uniqueness .e. Constraints. not to be confused with a base table). i.

drop materialized view mv . create materialized view log on t2 with primary key.table_name = 'MV' .inner join user_ind_columns ic using ( index_name ) where i. COUNT(*) ROW_COUNT from t2 group by t_key .--------.--------------SYS_C0019959 UNIQUE KEY In the next example Oracle automatically generates a function based index. sequence ( t_key. INDEX_NAME UNIQUENES COLUMN_NAME --------------. amt ) including new values . rowid. create materialized view mv refresh fast on commit as select t_key.

column_name .. INDEX_NAME UNIQUENES COLUMN_NAME COLUMN_EXPRESSION --------------.uniqueness . column column_expression format a35 select index_name .--------.table_name = 'MV' . ic.column_expression from user_indexes i inner join user_ind_columns ic left outer join user_ind_expressions ie using ( index_name ) using ( index_name ) where ic.----------------------------------I_SNAP$_MV UNIQUE SYS_NC00003$ SYS_OP_MAP_NONNULL("T_KEY") .--------------. ie. i.

Do not attempt to use it in your own code. In the following example we will add an index on the T_KEY column. i. select index_name .column_name from user_indexes i inner join user_ind_columns ic using ( index_name ) where i. ic.table_name = 'MV' .uniqueness . create index MY_INDEX on mv ( T_KEY ) .--------.--------------I_SNAP$_MV MY_INDEX UNIQUE SYS_NC00003$ NONUNIQUE T_KEY . See Nulls and Equality: SQL Only for additional info.(Note that SYS_OP_MAP_NONNULL is an undocumented Oracle function. INDEX_NAME UNIQUENES COLUMN_NAME --------------.) Adding Your Own Indexes We can add out own indexes to MV just as we would a regular table.

T_KEY ROW_COUNT ---------.---------2 2 Execution Plan ---------------------------------------------------------Plan hash value: 2793437614 ------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------| | |* 0 | SELECT STATEMENT 1 | 2 | | | | 1 | 1 | 1 | 26 | 26 | | 2 2 1 (0)| 00:00:01 | (0)| 00:00:01 | (0)| 00:00:01 | MAT_VIEW ACCESS BY INDEX ROWID| MV INDEX RANGE SCAN | MY_INDEX | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- . set autotrace on explain set linesize 95 select * from where mv t_key = 2 .To confirm that Oracle uses our index in queries let's turn SQL*Plus's Autotrace feature on and execute a query.

Materialized Views ENABLE QUERY REWRITE Materialized views can be useful for pre-calculating and storing derived values such as AMT_MAX in the following snippet. sequence ( t_key. drop materialized view log on t2 . Cleanup drop materialized view mv . create materialized view mv refresh fast on commit . amt ) including new values . rowid. create materialized view log on t2 with primary key.dynamic sampling used for this statement Note how the optimizer chose an INDEX RANGE SCAN from MY_INDEX in step 2.2 .access("T_KEY"=2) Note ----.

---------1 2 300 250 faster than its equivalent query. T_KEY AMT_MAX ---------. Such materialized views make queries like this select t_key. max( amt ) as amt_max FROM T2 group by t_key order by t_key . amt_max FROM MV order by t_key . . select t_key.as select t_key. MAX( AMT ) AMT_MAX from t2 group by t_key .

Next we collect statistics on the materialized view to help Oracle optimize the query rewrite process. alter materialized view mv ENABLE QUERY REWRITE .---------1 2 300 250 Wouldn't it be nice if Oracle could use the information in MV to resolve this last query too? If your database has a feature called Query Rewrite available and enabled this happens automatically. (See Gotcha . To see it in action we first need to make the materialized view available to Query Rewrite like this. execute dbms_stats. Finally we can confirm Oracle will use the materialized view in queries by turning SQL*Plus's Autotrace feature on.) Note that materialized views which do not include the ENABLE QUERY REWRITE clause will have Query Rewrite disabled by default.ORA-00439 below if you encounter an ORA-00439 error at this step. 'MV' ) . set autotrace on explain set linesize 95 .gather_table_stats( user.T_KEY AMT_MAX ---------.

max( amt ) as amt_max . alter session set QUERY_REWRITE_ENABLED = FALSE . select t_key.select t_key. Without the Query Rewrite feature the execution plan would look like this.---------1 2 300 250 Execution Plan ---------------------------------------------------------Plan hash value: 446852971 -------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------| | | 0 | SELECT STATEMENT 1 | 2 | SORT ORDER BY | | | | | 2 | 2 | 2 | 14 | 14 | 14 | 4 4 3 (25)| 00:00:01 | (25)| 00:00:01 | (0)| 00:00:01 | MAT_VIEW REWRITE ACCESS FULL| MV -------------------------------------------------------------------------------------- Note how the optimizer chose to access MV for its pre-calculated MAX(AMT) values in line 2 even though the query itself made no mention of MV. max( amt ) as amt_max FROM T2 group by t_key order by t_key . T_KEY AMT_MAX ---------.

FROM T2 group by t_key order by t_key .---------1 2 300 250 Execution Plan ---------------------------------------------------------Plan hash value: 50962384 --------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------| | | 0 | SELECT STATEMENT 1 | 2 | SORT GROUP BY | | | | | 5 | 5 | 5 | 130 | 130 | 130 | 4 4 3 (25)| 00:00:01 | (25)| 00:00:01 | (0)| 00:00:01 | TABLE ACCESS FULL| T2 --------------------------------------------------------------------------- Note ----. Each time this query is executed it has to re-calculate MAX(VAL) from the information in T2 for each .dynamic sampling used for this statement Note how the optimizer chose to access T2 this time. T_KEY AMT_MAX ---------.

create materialized view mv2 refresh fast on commit ENABLE QUERY REWRITE as select t_key . from t2 * ERROR at line 9: ORA-00439: feature not enabled: Materialized view rewrite Cleanup alter session set query_rewrite_enabled = true . Gotcha . count(amt) as amt_count from t2 group by t_key . If you attempt to use ENABLE QUERY REWITE in an Oracle database where the feature is not enabled you will receive an ORA-00439 error. a more expensive approach than simply selecting pre-calculated column values from MV is. count(*) as row_count .group. set autotrace off .ORA-00439 The materialized view query rewrite feature is not available in Oracle XE and some other Oracle configurations.

USER from t * ERROR at line 3: ORA-30353: expression not supported for query rewrite . Attempting to violate these restrictions results in an error.  create materialized view mv ENABLE QUERY REWRITE as select key. an expression containing the USER pseudo column or the SYSTIMESTAMP function. as select key.g. drop materialized view log on t2 . val. e. USER from t . val. Materialized Views Query Rewrite Restrictions and Capabilities Restrictions Materialized views with the following characteristics cannot have query rewrite enabled: the defining query references functions which are not DETERMINISTIC  an expression in the defining query is not repeatable.drop materialized view mv .

set long 5000 select my_mv_capabilities( 'MV'. In the snippets below we will use this same utility to explore rewrite capabilities. 'REWRITE' ) as mv_report from dual .Capabilities A few different materialized view query rewrite capabilities exist. In EXPLAIN_MVIEW we used a utility called MY_MV_CAPABILITIES to explore a materialized view's refresh capabilities. First lets look at a simple. create materialized view mv DISABLE QUERY REWRITE as select key. single table materialized view with query rewrite disabled. MV_REPORT -------------------------------------------------------------------------------- Not Capable of: REWRITE REWRITE_FULL_TEXT_MATCH query rewrite is disabled on the materialized view . val from t .

REWRITE_PARTIAL_TEXT_MATCH query rewrite is disabled on the materialized view REWRITE_GENERAL query rewrite is disabled on the materialized view This materialized view obviously has no rewrite capabilities available to it.) Enabling query rewrite on the materialized view changes this. alter materialized view mv ENABLE QUERY REWRITE . (Descriptions of each capability name are available at Table 8-7 CAPABILITY_NAME Column Details. 'REWRITE' ) as mv_report from dual . select my_mv_capabilities( 'MV'. MV_REPORT -------------------------------------------------------------------------------- Capable of: REWRITE REWRITE_FULL_TEXT_MATCH REWRITE_PARTIAL_TEXT_MATCH .

create materialized view mv enable query rewrite as select key.REWRITE_GENERAL Now all rewrite capabilities are available. select my_mv_capabilities( 'MV'. but not others. val from T@REMOTE . 'REWRITE' ) as mv_report from dual . drop materialized view mv . MV_REPORT -------------------------------------------------------------------------------- Capable of: REWRITE REWRITE_PARTIAL_TEXT_MATCH REWRITE_GENERAL . If the materialized view happened to referenced a remote table then some rewrite capabilities would be available.

Not Capable of: REWRITE_FULL_TEXT_MATCH T mv references a remote table or view in the FROM list Cleanup drop materialized view mv . .

Sign up to vote on this title
UsefulNot useful