Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle - How to create a materialized view with FAST REFRESH and JOINS

So I'm pretty sure Oracle supports this, so I have no idea what I'm doing wrong. This code works:

CREATE MATERIALIZED VIEW MV_Test   NOLOGGING   CACHE   BUILD IMMEDIATE    REFRESH FAST ON COMMIT    AS     SELECT V.* FROM TPM_PROJECTVERSION V; 

If I add in a JOIN, it breaks:

CREATE MATERIALIZED VIEW MV_Test   NOLOGGING   CACHE   BUILD IMMEDIATE    REFRESH FAST ON COMMIT    AS     SELECT V.*, P.* FROM TPM_PROJECTVERSION V     INNER JOIN TPM_PROJECT P ON P.PROJECTID = V.PROJECTID 

Now I get the error:

ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view

I've created materialized view logs on both TPM_PROJECT and TPM_PROJECTVERSION. TPM_PROJECT has a primary key of PROJECTID and TPM_PROJECTVERSION has a compound primary key of (PROJECTID,VERSIONID). What's the trick to this? I've been digging through Oracle manuals to no avail. Thanks!

like image 273
Mike Christensen Avatar asked Sep 21 '11 18:09

Mike Christensen


People also ask

How do I make materialized view refresh faster?

For fast refresh to be possible, the SELECT list must contain all of the GROUP BY columns (if present), and there must be a COUNT(*) and a COUNT(column) on any aggregated columns. Also, materialized view logs must be present on all tables referenced in the query that defines the materialized view.

Can we use joins in materialized view?

One of the most common follow-on questions we receive is whether materialized views can support joins. The answer is emphatically yes.

What is the difference between fast refresh and complete refresh in materialized view?

A fast refresh requires having a materialized view log on the source tables that keeps track of all changes since the last refresh, so any new refresh only has changed (updated, new, deleted) data applied to the MV. A complete refresh does what it says: it completely refreshes all data in the MV.

Why does materialized view taking long time to create?

When you create a materialized view, you actually create a copy of the data that Oracle takes care to keep synchronized (and it makes those views somewhat like indexes). If your view operates over a big amount of data or over data from other servers, it's natural that the creating this view can take time.


2 Answers

To start with, from the Oracle Database Data Warehousing Guide:

Restrictions on Fast Refresh on Materialized Views with Joins Only

...

  • Rowids of all the tables in the FROM list must appear in the SELECT list of the query.

This means that your statement will need to look something like this:

CREATE MATERIALIZED VIEW MV_Test   NOLOGGING   CACHE   BUILD IMMEDIATE    REFRESH FAST ON COMMIT    AS     SELECT V.*, P.*, V.ROWID as V_ROWID, P.ROWID as P_ROWID      FROM TPM_PROJECTVERSION V,          TPM_PROJECT P      WHERE P.PROJECTID = V.PROJECTID 

Another key aspect to note is that your materialized view logs must be created as with rowid.

Below is a functional test scenario:

CREATE TABLE foo(foo NUMBER, CONSTRAINT foo_pk PRIMARY KEY(foo));  CREATE MATERIALIZED VIEW LOG ON foo WITH ROWID;  CREATE TABLE bar(foo NUMBER, bar NUMBER, CONSTRAINT bar_pk PRIMARY KEY(foo, bar));  CREATE MATERIALIZED VIEW LOG ON bar WITH ROWID;  CREATE MATERIALIZED VIEW foo_bar   NOLOGGING   CACHE   BUILD IMMEDIATE   REFRESH FAST ON COMMIT  AS SELECT foo.foo,                                      bar.bar,                                      foo.ROWID AS foo_rowid,                                      bar.ROWID AS bar_rowid                                 FROM foo, bar                               WHERE foo.foo = bar.foo; 
like image 85
Allan Avatar answered Sep 20 '22 14:09

Allan


Have you tried it without the ANSI join ?

CREATE MATERIALIZED VIEW MV_Test   NOLOGGING   CACHE   BUILD IMMEDIATE    REFRESH FAST ON COMMIT    AS SELECT V.*, P.* FROM TPM_PROJECTVERSION V,TPM_PROJECT P  WHERE  P.PROJECTID = V.PROJECTID 
like image 21
steve godfrey Avatar answered Sep 21 '22 14:09

steve godfrey