Skip to Main Content
  • Questions
  • Refreshing of Materialized Views with Indexes

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Sameer.

Asked: March 22, 2017 - 4:53 pm UTC

Last updated: April 03, 2017 - 12:48 am UTC

Version: 11.2.0.4 Enterprise

Viewed 10K+ times! This question is

You Asked

Hello,

All of our MV's are built as completely refresh-able, on-demand, with nologging, as shown below:-

CREATE MATERIALIZED VIEW mv_name
NOLOGGING
TABLESPACE "DATA_SPACE"
USING INDEX TABLESPACE "INDEX_SPACE"
REFRESH ON DEMAND
COMPLETE
AS
--SELECT Text as an example only (this SQL query Text gets populated dynamically from either a CLOB column or from a CLOB procedure's IN parameter with SELECT always having compiler hints as shown:

SELECT /*+ PARALLEL(8) NOLOGGING */ *
FROM tb_name_1
UNION
SELECT /*+ PARALLEL(8) NOLOGGING */ *
FROM tb_name_2
;


Once the MV is created and stats gathered, the Analysts begin using the MV and sometimes, depending on the performance and reporting needs, we may have to add BITMAP, UNIQUE and NON-UNIQUE indexes on multiple columns on the MV. Each MV may have a different refresh schedule depending on the data-source's own refresh schedule.

The main objective is to build a "lean" refresh operation, as much as possible, which will hopefully, result into refreshes that will take the least amount of time (as much as we can even though some refreshes will take longer due to the nature of the SQL query, etc.).


Upon reading the 11.2 documentation for DBMS_MVIEW.REFRESH, it mentions that setting the parameter atomic_refresh => FALSE will take care of (a) disabling, (b) re-building, and (c) computing stats for UNIQUE indexes ONLY.

Does this mean that for all "other" index types present on the MV, like BITMAP and NON-UNIQUE, I have to manually:-

(a) Disable all BITMAP and NON-UNIQUE indexes (ignoring UNIQUE indexes) before running DBMS_MVIEW.REFRESH,

(b) Run the DBMS_MVIEW.REFRESH with parameters method => 'C' and atomic_refresh => FALSE,

(c) Rebuild all BITMAP and NON-UNIQUE indexes (hoping the UNIQUE indexes will be re-built in the step above),

(d) Gather Table Stats that will compute stats for both the Table as well as all the Indexes.


Appreciate any advise :)

and Chris said...

No, Oracle Database refreshes non-unique indexes and gather stats on them too with non-atomic refreshes:

create table t2 ( x , y ) as
  select rownum x, mod(rownum, 5) y from dual connect by level <= 1000;
create table t1 ( x , y ) as
  select rownum x, mod(rownum, 3) y from dual connect by level <= 1000;
  
create materialized view mv_name
refresh on demand 
as
  select t1.* from t1
  union 
  select t2.* from t2;
  
create index iy on mv_name(y);

select status, num_rows from user_indexes
where  index_name = 'IY';

STATUS  NUM_ROWS  
VALID   1,800 
  
insert into t1
  select rownum+1000 x, mod(rownum, 3) y from dual connect by level <= 1000;
insert into t2
  select rownum+1000 x, mod(rownum, 5) y from dual connect by level <= 1000;
commit;

exec dbms_mview.refresh('mv_name', atomic_refresh => false);

select status, num_rows from user_indexes
where  index_name = 'IY';

STATUS  NUM_ROWS  
VALID   3,600   

select count(*) from mv_name;

COUNT(*)  
3,600   


In terms of making your refresh faster, it's worth investigating if you can go for regular fast refreshes. You have to go for complete refreshes with union. But you can fast refresh with union all. (Just make sure you add a marker column: https://jonathanlewis.wordpress.com/2016/07/12/union-all-mv/ )

So you could:

- Create a fast refresh union all MV
- A complete refresh MV on top of this returning the distinct rows

This may help if the intersection of the two tables is "small". If so, the distinct MV will have much less data to process => it'll be faster.

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Follow-up

Sameer Premji, March 30, 2017 - 6:48 pm UTC

Thanks Chris for your input.

Sadly, we do not have the ability to do regular fast refreshes (but only complete refreshes on-demand) as all of our data-sources are made available to us as VIEWS only, by the DBA team.

We then perform various SELECT queries with various filters and joins from these "source" VIEWS to create tables containing only a subset of records depending on the needs, and store these smaller tables in our schemas for further analysis project work.

So, to confirm again, if a user does supply a long SELECT query text to be built as an MV object (using the procedure I'm building) and if that SELECT query text somewhere has a "UNION" word, then I should not bother with replacing the word "UNION" with "UNION ALL" correct, since it's a complete refresh anyways?

On another note, I have created 3 procedures that would dynamically create a TABLE, VIEW and MV, using DBMS_SQL, given a SELECT query text from the user.

In all of my procedures, I am validating if the first executable statement starts with the word "SELECT ", however, one of the users in my team does like to use "WITH" clause quite a lot, especially when creating a table using the CREATE TABLE AS WITH....and when creating VIEWS and MV objects.

Do you foresee any negative implications (perhaps, performance) when using "WITH" clause within a DDL code execution operation?

Thanks once again for your help :)
Connor McDonald
April 03, 2017 - 12:48 am UTC

"So, to confirm again, if a user does supply a long SELECT query text to be built as an MV object (using the procedure I'm building) and if that SELECT query text somewhere has a "UNION" word, then I should not bother with replacing the word "UNION" with "UNION ALL" correct, since it's a complete refresh anyways? "

No, this not correct. A UNION will do *more* work than a UNION ALL (and of course might return different results). If you can gurantee in the definition that the results will be mutually exclusive, then use UNION ALL.

eg

select * from T where col = 1
union
select * from T where col = 2

is better written as

select * from T where col = 1
union all
select * from T where col = 2

because there will not be any need to sort/de-dup the result.

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here