Oracle - Materialized View still accessible during complete refresh. How does this work? - oracle

In one of our applications, we have a massive Materialized View that refreshes three times a day, and takes seven hours to refresh. (Not ideal, I know). This perplexed me, because I surely thought that users and sessions could not access this materialized view while it was being refreshed, but apparently they can!. (The type of refresh is a complete refresh)
During a complete refresh, to my understanding, the existing dataset is dropped and the query is then re-executed. If this is true, then how are users/other sessions able to access the materialized view while the materialized view is being refreshed?

There are two different ways that a complete refresh can happen-- an atomic refresh or a non-atomic refresh. An atomic refresh simply issues a DELETE to delete all the rows in the materialized view and then does an INSERT to insert the new data. This is all within a single transaction so Oracle's standard multi-version read consistency architecture lets Oracle show other sessions the old data until the refresh completes. In a non-atomic refresh, Oracle does a TRUNCATE on the materialized view and then a direct-path INSERT to insert the new data. This is substantially more efficient but since TRUNCATE is DDL, it means that the old data is not visible to other sessions during the refresh.

Related

Partial refresh on Materialized View

We have a table TB_1 which has monthly and weekly data partitioned by monthly and weekly columns. We also have materialized view MV_1 inherited from the table TB_1.
We would like to refresh the materialized view by certain weekly or monthly basis.
Not sure how we can filter out weekly or monthly changes from all the changes captured in the materialized log for partial refresh.
Right now we are thinking to have a flag column in TB_1. By clearing the materialized log and updating the flag, We think we can achieve this.
Is there anyway efficient way than the process for partial refresh on specific criteria?
We have a similar case here: the solution we found was to partition the materialized view month by month (using PCT ). If you have this as an option in your licensing, this could be a solution. Then you must partition the "details tables", TB_1, and probably the "details tables" of MV_1.
execute dbms_mview.refresh(
list => 'your_partitioned_mview'
, method => 'P' -- this is where PCT is specified
, atomic_refresh => false
);
There are also other solution on Is it possible to partially refresh a materialized view in Oracle? .
edit:
I'd say the solution of a fast refresh using a "to be refreshed" flag is worth being tried. Not sure you need to clear the Mview log beforehand. Just changing the value of the flag for the record to be updated should work. Here is a nice howto I found.
If you have Oracle 12.2, they introduced real-time Mviews, which might be what you are looking for...
Oracle 12.2 introduced the concept of real-time materialized views, which allow a statement-level wind-forward of a stale materialised view, making the data appear fresh to the statement. This wind-forward is based on changes computed using materialized view logs, similar to a conventional fast refresh, but the operation only affect the current statement. The changes are not persisted in the materialized view, so a conventional refresh is still required at some point.
#use416, please keep us posted for what actually worked for your case.

Get current time, on commit, with oracle database

When inserting a row I want to set a column, equal to the current time on commit.
If I use default value sysdate on the column, it uses the current time at insert (which could be significantly different to commit time). If I use an on insert trigger, it again uses the time at the insert - not the actual commit.
Are there any possible solutions to get current time on commit with oracle ?
There are options. They may be rather more heavyweight than you were hoping for, though.
You could create a fast-refreshable materialized view that refreshes on commit and put a trigger on that materialized view that would fire when the row commits. That would mean, though, that you'd need a materialized view log on the base table so your insert would incur the overhead of writing to the table and the log plus you'd incur the cost of the materialized view refresh when you committed. If you ever had to do a full refresh of the materialized view, you'd need to make sure to turn off the trigger as well. That's quite a few moving pieces that will add complexity to your system.
Depending on the Oracle version, you might be able to enable Flashback Data Archive (also known as Total Recall) which would record the SCN and timestamp of when each version of data was committed. The downside there is that you'd then have a potentially large history table that is likely tracking a bunch of information that you don't care about.

How to create materialized view for a table?

I am having a hard time to understand all about materialized views in Oracle. Would someone can help me and explain it to me in layman's term?
In layman's terms:
Materialized view is a view (meaning: "a select stored in the database under a name") that is, literally, materialized (meaning: "its contents are actually stored in a dedicated table, usually of the same name as the mview").
The biggest advantage of mview:
The query (however complex it is) does not have to be re-executed each time the mview is being queried from. The actual data are read from the underlying table.
The biggest disadvantage of mview:
If the source data of the mview change, the respective mview does not (automatically (usually)). You have to refresh it.
That's about it about materialized views. For further reading I advise you to read more about:
materialized view fast refresh
fast refresh on commit
periodical vs. on-demand refreshing
query rewrite (a wonderfully useful feature!)
partition change tracking
materializing on prebuilt tables (... which might be considered entering the black magic area of mviews ;-))

Oracle - Updating Materialized Views

How can I update a materialized view? Is there any downside to updating materialized views? I'm in a situation where I can either
Update the materialized view (OR)
Copy the records to another table, update them, truncate or drop the materialized view table, insert the updated records back into the materialized view.
These two options revolve around the long amount of time required to rebuild the materialized view (literally 5+ days).
Version : Oracle 10g
The intention of a materialized view is to store the results of some complex long running query that the query rewrite mechanism can use to save lots of time. It looks like the sql that is used to build the MV needs some tweeking.
You cannot update an MV, unless you meant doing a full/fast refresh/rebuild.
What is eating the time in during the MV refresh? Did you check the addm reports?
Did you configure full or fast refreshes?

Is it possible to partially refresh a materialized view in Oracle?

I have a very complex Oracle view based on other materialized views, regular views as well as some tables (I can't "fast refresh" it). Most of the time, existing records in this view are based on a date and are "stable", with new record sets having new dates.
Occasionally, I receive back-dates. I know what those are and how to deal with them if I were maintaining a table, but I would like to keep this a "view". A complete refresh would take around 30 minutes, but it only takes 25 seconds for any given date.
Can I specify that only a portion of a materialized view should be updated (i.e. the affected dates)?
Do I have to scrap the view and use a table and a procedure to populate or refresh a given date in that table?
Partition by date as in answer 3 (skaffman).
You could just do the refresh of a normal mv(table_refreshed below) and than use the exchange keyword i.e.
ALTER TABLE all_partitions
EXCHANGE PARTITION to_calculate
WITH TABLE table_refreshed
WITHOUT VALIDATION
UPDATE GLOBAL INDEXES;
After more reading and judging by the lack of answers to this question, I come come to the conclusion that it is not possible to refresh a single partition of a materialized view.
If you can give a syntax example that proves otherwise, I will happily mark your answer the accepted one.
To others who might find this questions useful in the future: you might also want to know that in Oracle 10g, refreshing a partition (or any mview) will cause Oracle to issue DELETE, followed by INSERT.
If this is giving you performance problems (like me), there is an option to use atomic_refresh => false, which will TRUNCATE, then INSERT /*+APPEND*/.
I have been able to refresh a single partition of a materialized view with partition change tracking.
It seems to require that the view is created with REFRESH FAST WITH ROWID option and DBMS_MVIEW.REFRESH is called with 'P' method.
You can partition materialized views just as you can with normal tables. Partition your mview by date, and then you can refresh only the required partition.

Resources