Get current time, on commit, with oracle database - oracle

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.

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.

Removing bloat from greenplum table

I have created some tables in Greenplum, performing insert update and delete operation. Regularly I am also performing vacuum operation. I Found bloat in it. Found solution to remove bloat https://discuss.pivotal.io/hc/en-us/articles/206578327-What-are-the-different-option-to-remove-bloat-from-a-table
However, if I truncate the table and reinsert the data, it removes bloat. Is it good practice to truncate the data from the table?
If you are performing UPDATE and DELETE statements on a heap table (default storage) and running VACUUM regularly, you will get some bloat by design. Heap storage, which is similar to the default PostgreSQL storage mechanism, provides read consistency using Multi-Version Concurrency Control (MVCC).
When you UPDATE or DELETE a record, the old value is still in the table and is able to be read by transactions that are still inflight and started before you issued the UPDATE or DELETE command. This provides the read consistency to the table.
When you execute a VACUUM statement, the database will mark the stale rows as available to be overwritten. It doesn't shrink the files. It just marks rows so they can be overwritten. The next time you execute an INSERT or UPDATE, the stale rows are now able to be used for the new data.
So if you UPDATE or DELETE 10% of a table between running VACUUM, you will probably have about 10% bloat.
Greenplum also has Append-Optimized (AO) storage which doesn't use MVCC and uses a visibility map instead. The files are bit smaller too so you should get better performance. The stale rows are hidden with the visibility map and VACUUM won't do anything until you hit the gp_appendonly_compaction_threshold percentage. The default is 10%. When you have 10% bloat in an AO table and execute VACUUM, the table will automatically get rebuilt for you.
Append-Optimized is called "appendonly" for backwards compatibility reasons but it does allow UPDATE and DELETE. Here is an example of an AO table:
CREATE TABLE sales
(txn_id int, qty int, date date)
WITH (appendonly=true)
DISTRIBUTED BY (txn_id);
Instead of truncate it is better to use drop the table, create the table and then insert the data.

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

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.

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