Can Materialized View fast refresh work when based on views are based on tables? - oracle

I am reviewing my team's database setup, particularly focusing on Materialized Views. In most cases, we are currently doing 'Complete' refreshes, and I want to move to doing fast refreshes.
In some cases, this is straight forward -- the MV is based directly on a table on our source database, and I can enable MVIEW LOGS on the table and recreate the MV.
But in a number of cases, the MVs are based on a combination of other MVs, and Views, etc, that go several levels deep before I get to the tables on our source database.
In these cases, if I track down the ultimate source tables, will enabling MVIEW LOGS on them allow the top MV and any intermediate MVs, to use fast refresh?

The Oracle documentation contains an example for a FAST REFRESH of a materialized view based on an UNION ALL view:
CREATE VIEW view_with_unionall AS
(SELECT c.rowid crid, c.cust_id, 2 umarker
FROM customers c WHERE c.cust_last_name = 'Smith'
UNION ALL
SELECT c.rowid crid, c.cust_id, 3 umarker
FROM customers c WHERE c.cust_last_name = 'Jones');
CREATE MATERIALIZED VIEW unionall_inside_view_mv
REFRESH FAST ON DEMAND AS
SELECT * FROM view_with_unionall;
So in principle, you can indeed fast refresh materialized views based on views.
Some things to note:
there are a couple of restrictions for fast refreshable materialized views. E.g. you cannot use ROWNUM, SYSDATE or HAVING. See the docs for details
somewhat counterintuitively, a FAST REFRESH is not always faster than a COMPLETE REFRESH. This depends on the amount of data that has changed since the last refresh; IMHO, Oracle should have used the term INCREMENTAL REFRESH instead

Oracle provides a procedure for that: DBMS_MVIEW.EXPLAIN_MVIEW
You can use this procedure to check whether your Materialized Views is capable for FAST REFRESH, it also tells you the reason why it is not.
For me the most strange restriction for FAST REFRESH is: When you join several tables you have to use the (old) Oracle Join syntax, ANSI join syntax does not work. Some time ago a created a case at Oracle support for this issue, however the answer from Oracle was: "This is not a bug, it is just a lack of documentation."(!)
I don't know if it still applies for Oracle 12c version.

Related

Materialized view creation is fast but refresh takes hours on Oracle 19c

Recently I need to create several materialized views on Oracle 19c, all of the base tables are locate on a remote oracle database, the query uses dblink to connect the tables, and fast refresh is not allowed.
Most of them can complete refreshment in seconds after add some hints on them, like use_hash etc. But when create the one with union on the query, the hints do not work at all, luckily there is only one union, so I split the query to two parts, but another issue emerges, one of the materialized view only takes no more than 10 seconds for creation, but it takes hours even days cannot complete refreshment. I searched on web and got below answers:
use dbms_mview.refresh(mv_name, 'C', atomic_refresh=>false). This solution does not work.
fast refresh. The solution does not allowed.
Instead to do refresh, re-create the materialized view every time, it is a workaround, but not a solution.
Use hint optimizer_features_enable(9.0.0), I simulated the issue on a table (as I cannot insert into...select... on materialized view), seems the hint does work, but when I tried to apply the hint on the materialized view, from the execution plan I can see that the hint has been ignored. I also tried to add alter session set optimizer_features_enable='9.0.0' on scheduler job before the dbms_refresh.refresh(mv_name), but it does not work. Would like to know are there anyone have any idea on this problem? Thank you.
Jonathan from oracle community just gave me a solution for my specific query. As all the fields of my query come from remote database except the systimestamp function, so I can separate the function to the outer select statement and make all the remote fields as sub-select statement then add no_merge hint to it, this will make remote database optimizer come to play.
SELECT systimestamp, v.*
FROM (
my original query with /*+ no_merge */
) v;

Creating Materialized view in oracle taking forever

I have following query which has select query that returns data in 5sec. But when I add create materialized view command infront it takes ever for the query to create materialized view.
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.
From docs.oracle.com:
A materialized view is a replica of a target master from a single
point in time.
Just for "yuks", try
create table temp_tab nologging as select ...
I've seen cases where MV creation is long for some reason, probably logging.
Also, query development tools sometimes begin returning the data to the screen right away, but if you "paged" to the last row, you would find out how long it really takes to get all the data.
You should profile the select statement with explain plan and understand the table cardinality, indexes, waits states when running, ... in order to see if the query needs tuning.

Oracle materialized view question

I have a table that holds information about different events, for example
CREATE TABLE events (
id int not null primary key,
event_date date, ...
)
I realized that 90% of all queries access only today events; the older rows are stored for history and eventually moved to an archive table.
However, events table is still large, and I wonder if I can improve the performance by creating a materialized view that has something like WHERE event_date = trunc(sysdate) and maybe index on event_date ? Is it allowed at all?
Thanks
yes this is allowed see "primary key materialized view":
Primary key materialized views may contain a subquery so that you can
create a subset of rows at the remote materialized view site
and "complex materialized view"
If you refresh rarely and want faster query performance, then use
Method A (complex materialized view).
If you refresh regularly and can sacrifice query performance, then use Method B (simple materialized view).
at http://download.oracle.com/docs/cd/B10500_01/server.920/a96567/repmview.htm
In your example chances are good IMHO that this is not a "complex materialized view":
CREATE MATERIALIZED VIEW events_today REFRESH FAST AS
SELECT * FROM EVENT WHERE event_date = trunc(sysdate);
Just try it and see if Oracle accepts it with the REFRESH FAST clause.
EDIT - another option:
Depending on your DB Edition (Enterprise + Partitioning) and Version (11gR2) you could use a new Oracle feature called INTERVAL partitioning to define "daily partitions" within the existing table. This way most of your queries get alot faster without effectively duplicating the data - see http://www.oracle.com/technetwork/database/options/partitioning/twp-partitioning-11gr2-2009-09-130569.pdf

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.

How can I tell if a Materialized View in Oracle is being used?

We have some Materialized views in our Oracle 9i database that were created a long time ago, by a guy no longer working here. Is there an easy (or any) method to determine whether Oracle is using these views to serve queries? If they aren't being used any more, we'd like to get rid of them. But we don't want to discover after the fact that those views are the things that allow some random report to run in less than a few hours. The answer I'm dreaming of would be something like
SELECT last_used_date FROM dba_magic
WHERE materialized_view_name = 'peters_mview'
Even more awesome would be something that could tell me what actual SQL queries were using the materialized view. I realize I may have to settle for less.
If there is a solution that requires 10g, we are upgrading soon, so those answers would be useful also.
Oracle auditing can tell you this once configured as per the docs. Once configured, enable it by "AUDIT SELECT ON {name of materialized view}". The audit trail will be in the AUD$ table in the SYS schema.
One method other than auditing would be to read the v$segment_statistics view after one refresh and before the next refresh to see if there have been any reads. You'd have to account for any automatic statistics collection jobs also.
V$SQLAREA table has two columns which help identify the queries executed by the database.
SQL_TEXT - VARCHAR2(1000) - First thousand characters of the SQL text for the current cursor
SQL_FULLTEXT - CLOB - All characters of the SQL text for the current cursor
We can use this columns to find the queries using the said materialized views

Resources