Skip to Main Content
  • Questions
  • Refresh "complex" materialized view with a trigger

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, John.

Asked: March 12, 2001 - 6:25 am UTC

Last updated: March 19, 2017 - 5:18 am UTC

Version: 8.1.6

Viewed 10K+ times! This question is

You Asked

We have a "complex" materialized view which can only be
refreshed on demand. We want to execute the refresh using a trigger so that as soon as a user updates certain tables, the update statement triggers the refresh of the materialized view.

The DBMS_MVIEW package can not be used in a trigger because it contains a commit. We tried using pragma AUTONOMOUS_TRANSACTION
which is of course useless because the autonomous transaction
does not "see" the changes the user made.

Question:
How is it possible to refresh a "complex" materialized view using a trigger.



and Tom said...

You can do it asynchronously with DBMS_JOB.

As you found, you cannot use the refresh in the trigger because of the commit. Doing it autonomously doesn't work either since the changes are not visible to any other session yet. By using DBMS_JOB in the following fashion:


create or replace trigger X
after insert or update or delete on T
declare
l_job number;
begin
dbms_job.submit( l_job, 'dbms_mview.refresh( ''MV_NAME'' );' );
end;

shortly after you commit, not right away but shortly, the job will run. You need to set:

job_queue_interval
job_queue_processes

for dbms_job to work (but if you are using MV's you probably already have this setup).


Rating

  (11 ratings)

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

Comments

RE: refresh "complex" materialized view with a trigger

John Muyres, March 12, 2001 - 11:01 am UTC

Thank you for your response.

We did think about the suggested solution but rejected it because:
1. The dependency on job_queue_interval. There is a small time interval before the refresh. In that interval MV data is not correct.

2. The fact that the master tables are almost static (insert/update takes place only a few times a year) which doesn't warrent the extra overhead.

Perhapse yet an other solution is posible ?

A reader, March 12, 2001 - 12:43 pm UTC


Works great but ...

Dave, March 07, 2002 - 5:05 pm UTC

We found this response to be very helpful but we are having trouble implementing it. It seems to work great if the schema owner makes the change that cause the trigger to fire. However, when another user (who has privilege to change the master table) makes a change, the job gets queued up but fails when picked up for execution. We think this is because the LOG_USER is not the schema owner.

Any ideas?

Tom Kyte
March 07, 2002 - 7:26 pm UTC

make that trigger be:

ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace trigger X
  2  after insert or update or delete on T
  3  declare
  4     l_job number;
  5  begin
  6     dbms_job.submit( l_job, 'dbms_mview.refresh( ''OPS$TKYTE.T_MV'' );' );
  7  end;
  8  /

Trigger created.

that is, put the SCHEMA NAME in the refresh call (else dbms_mview puts USER in there and it'll try to refresh USER.T_MV and that mv doesn't exist.

sorry about that! 

perfect

DAVE, March 08, 2002 - 1:55 pm UTC


JOB Question

Ashok, September 26, 2002 - 6:01 pm UTC

dbms_job.submit( lv_checkjob_num, 'DEAL_REFRESH_PACKAGE.deal_mv_refresh;' );

I have submitted JOB command to refresh the materailized view but nothing happens why?i am able to see the record inuser_jobs

I checked the JOB_que_processes = 1 and job_QUE_INTERVAL = 60 sec.
After changing JOB_QUE_PROCESSES we have shutdown and restart?we are running oracle 8.1.7.4


Tom Kyte
September 26, 2002 - 6:30 pm UTC

add

commit;



sure you can see the job -- but, until you commit it -- the job queue process cannot see it.

Time Interval Problem

Tony, September 27, 2002 - 12:19 am UTC

Hi Tom,

1. Let us assume that job_queue_interval=60 seconds and the number of jobs are too huge to finish within 60 seconds. Next Job execution should start even if the current queue is not ye over. What will happen in this case?

2. What will be the impact on DB performance if so many complex jobs are scheduled?


Tom Kyte
September 27, 2002 - 7:37 am UTC

1) the job queue process will start by sleeping 60 seconds.

it will wake up and run every job in the queue that is ready to run.

it will then sleep 60 seconds.

it will wake up and run ........



2) think about it. same thing that would happen if you fired up N sqlplus sessions and ran the procedures interactively.

Refreshing Materialized view in a Group

Ashok, October 07, 2002 - 9:18 am UTC

When i try to refresh the materialized view in a group(using dbms_refresh.refresh('Group Name') it is supposed to do delete then Insert.If above statement is correct why i am getting zero record in the Middle of refresh when i try to do count(*) from different session......

Tom Kyte
October 07, 2002 - 9:35 am UTC

turn on sql_trace, run the dbms_refresh and look at the sql.

Maybe you didn't actually make a group -- not seeing your statements, I cannot really tell. But the sql_trace will show you the exact sql being used.

Refreshing Materialized view in a Group

Ashok, October 07, 2002 - 10:21 am UTC

It's doing delete & Insert ,i found it writing a trigger on a MV table for delete.The command i used to create a group is.
Begin
dbms_refresh.make(
name =>'deal_dtl_refresh',
list =>'deal_dtl_mv',
next_date =>sysdate,
interval =>'sysdate+1/24',
implicit_destroy =>true);
end;


Tom Kyte
October 07, 2002 - 12:50 pm UTC

If it does a delete + insert and you don't see any commit records in there (in the tracefile) then what you observed must be explained some other way (eg: you made a mistake somewhere and what you think happened did not happen that way).




Refreshinh Materialized View

Ashok, October 07, 2002 - 10:39 am UTC

>>turn on sql_trace, run the dbms_refresh and look at the >>sql
Tom You are right it's doing Truncate & Insert Instead of delete and Insert.What i am doing wrong here,is my creating MV group is wrong.
This is how i created the MV group
Begin
dbms_refresh.make(
name =>'deal_dtl_refresh',
list =>'deal_dtl_mv',
next_date =>sysdate,
interval =>'sysdate+1/24',
implicit_destroy =>true);
end;


Tom Kyte
October 07, 2002 - 1:05 pm UTC

I see what it is now.

See
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1389964969205 <code>

you need at least 2 mv's in the list in order to get it to use delete+insert. If you have but one, just create a "dummy" MV (with a "where 1=0" predicate or something) in order to have two that can be refreshed together.

MV delete/insert vs truncate/insert-append

J, October 28, 2011 - 4:55 pm UTC

Hello Tom.

Hope all is well.
Similar to the delete/truncate question:

We have a large, complex MV (~280M rows).
We are running v11.2.0.2, and the MV script goes something like this:

create materialized view big_kahuna_mv
tablespace large_tabspace
nologging noparallel compress
build immediate refresh force
start with sysdate
next trunc(sysdate+1)+(2/24)
with primary key
as
select . . .
15 columns from 6 tables (sizes vary from 5M-400M rows)
using a WITH, UNION, etc. all sorts of conditions

In the table which was created, we had bitmap indexes on 5 of the columns.
The initial build and post-build index creation went pretty well (about 20 minutes).

But when the refresh time rolled around at 2:00am, we found that the refresh was doing a DELETE.
We were hoping for it to do a TRUNCATE + INSERT-APPEND.
After many hours of trying to delete all those rows and bitmaps, the SID was eventually euthanized.

There is no query rewrite considerations here.
The table access is via one or more of the bitmapped columns.
Our user's queries change on an ad hoc basis.
The table contents are to be refreshed on a daily basis.

Any thoughts as to how we might adjust the definition and/or management of the big MV?

Thanks and Best Regards,
- J
Tom Kyte
October 29, 2011 - 11:18 am UTC

use atomic_refresh => FALSE on the refresh call. You can use dbms_job to schedule the refresh using your custom options.

Remember that that the materialized view will "disappear" during the refresh....

Life Saver

Asadullah Baig, March 16, 2017 - 11:00 am UTC

This solution figuratively saved my life. I also had a complex materialized view which was ON DEMAND. This solution with the addition of the schema name before the materialized view saved my life. Tom I have a scenario which I would like to share with you.

Lets imagine there are 500 users which open up a page at the same time (some sort of timed form submission). On this page there are three views which are being used. All three views are complex, am I better off with a materialized view or the simple views. Is using the materialized view concept here valid, if not what are the alternatives.
Connor McDonald
March 19, 2017 - 5:18 am UTC

Materialized view is certainly one option.

RESULT_CACHE might be another if the tables are not that volatile. One person pays the price of working out the result, and everyone else benefits.

In all cases, start with the bare minimum, ie, just run the SQL's with the expected volume of sessions. If it runs ok...you're done. Dont introduce complexity just for the sake of it.

If it does *not* run OK, or does not scale sufficiently, *then* consider additional options.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library