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

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;

Related

How to (un)mark an Oracle table read-only for the owner?

In my Oracle instance I have a table. It existed just fine for many years without problems, I run thousands of queries per day on it (through my software), mostly selects and inserts, with rare (once-a-week) updates.
Today, a week after the last update, I ran an update against it and it failed with an ORA-00942: table or view does not exist.
I am the owner of that table. I'm pretty sure that database didn't change much during the week, certainly not this table.
I can select from it just fine: select * from table_x, but updates and inserts fail: insert into table_x select * from table_x where 1 = 0 with the weird ORA-00942.
Since I'm the owner, the usual visibility and privilege problems don't seem to apply, and googling, sadly, doesn't help. I'm sure I'm missing something really simple, so any suggestions are very welcome.
How did I make an Oracle table read-only (or invisible) for myself (the owner)?
It's partitioned (not sure if that helps). It's about 50GB in size, half of that indexes (not sure if that helps either).
EDIT: Here's a screenshot of the sample statement from PL/SQL Developer:
Once I ran the same situation, according to the trace file and little googling which referenced to Materialized View Log which is associated with master table.
Use the following command to drop the materialized view log
DROP MATERIALIZED VIEW LOG ON <table_x>

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

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.

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.

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