Continuing the previous post, what happens when there is an UPDATE to the source table ?
So, it is clear that UPDATES, too, go to the MLOG$ table.
What about multi-row operations ?
Wow ! Three rows updated in the Source Table translated to 6 rows in the MLOG$ table ! Each update row was represented by an DMLTYPE$$='D' and OLD_NEW$$='O' followed by a DMLTYPE$$='I' and OLD_NEW$$='N'. So that should mean "delete the old row from the materialized view and insert the new row into the materialized view" ??
(For the time being, we'll ignore SNAPTIME$$ being '01-JAN-00').
So an UPDATE to the Source Table of a Materialized View can be expensive during the UPDATE (as it creates two entries in the MLOG$ table) and for subsequent refresh's as well !
What happens when I refresh the Materialized View ?
The session trace file shows these operations (I've excluded a large number of recursive SQLs and SQLs that were sampling the data for optimisation of execution plans):
and this being the refresh (merge update) of the target MV
So, we see a large number of intensive operations against the MLOG$ Materialized View Log object.
And on the MV, there is a DELETE followed by a MERGE (UPDATE/IINSERT)
Two takeaways :
1. Updating the Source Table of a Materialized View can have noticeable overheads
2. Refreshing a Materialized View takes some effort on the part of the database
(Did you notice the strange year 2100 date in the update of the MLOG$ table?
.
.
.
.
.
.
SQL> select * from source_table;
        ID DATA_ELEMENT_1  DATA_ELEMENT_2  DATE_COL
---------- --------------- --------------- ---------
         1 First           One             18-AUG-19
         3 Third           Three           18-AUG-19
         4 Fourth          Four            18-AUG-19
SQL> select * from mlog$_source_table;
no rows selected
SQL> select * from rupd$_source_table;
no rows selected
SQL>
SQL> update source_table
  2  set data_element_2 = 'Updated', date_col=sysdate
  3  where id=4;
1 row updated.
SQL> select * from rupd$_source_table;
no rows selected
SQL> commit;
Commit complete.
SQL> select * from rupd$_source_table;
no rows selected
SQL> select * from mlog$_source_table;
        ID SNAPTIME$ D O
---------- --------- - -
CHANGE_VECTOR$$
--------------------------------------------------------------------------------
     XID$$
----------
         4 01-JAN-00 U U
18
8.4443E+14
SQL>
So, it is clear that UPDATES, too, go to the MLOG$ table.
What about multi-row operations ?
SQL> update source_table set id=id+100;
3 rows updated.
SQL> select * from rupd$_source_table;
no rows selected
SQL> select * from mlog$_source_table;
        ID SNAPTIME$ D O
---------- --------- - -
CHANGE_VECTOR$$
--------------------------------------------------------------------------------
     XID$$
----------
         4 01-JAN-00 U U
18
8.4443E+14
         1 01-JAN-00 D O
00
1.4075E+15
       101 01-JAN-00 I N
FF
1.4075E+15
         3 01-JAN-00 D O
00
1.4075E+15
       103 01-JAN-00 I N
FF
1.4075E+15
         4 01-JAN-00 D O
00
1.4075E+15
       104 01-JAN-00 I N
FF
1.4075E+15
7 rows selected.
SQL>
Wow ! Three rows updated in the Source Table translated to 6 rows in the MLOG$ table ! Each update row was represented by an DMLTYPE$$='D' and OLD_NEW$$='O' followed by a DMLTYPE$$='I' and OLD_NEW$$='N'. So that should mean "delete the old row from the materialized view and insert the new row into the materialized view" ??
(For the time being, we'll ignore SNAPTIME$$ being '01-JAN-00').
So an UPDATE to the Source Table of a Materialized View can be expensive during the UPDATE (as it creates two entries in the MLOG$ table) and for subsequent refresh's as well !
What happens when I refresh the Materialized View ?
SQL> execute dbms_session.session_trace_enable;
PL/SQL procedure successfully completed.
SQL> execute dbms_mview.refresh('MV_OF_SOURCE');
PL/SQL procedure successfully completed.
SQL> execute dbms_session.session_trace_disable;
PL/SQL procedure successfully completed.
SQL>
The session trace file shows these operations (I've excluded a large number of recursive SQLs and SQLs that were sampling the data for optimisation of execution plans):
update "HEMANT"."MLOG$_SOURCE_TABLE" 
set snaptime$$ = :1  
where snaptime$$ > to_date('2100-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS')
/* QSMQ VALIDATION */ ALTER SUMMARY "HEMANT"."MV_OF_SOURCE" COMPILE
select 1 from "HEMANT"."MLOG$_SOURCE_TABLE" 
where snaptime$$ > :1 
and ((dmltype$$ IN ('I', 'D')) or  (dmltype$$ = 'U' and old_new$$ in ('U', 'O') 
and   sys.dbms_snapshot_utl.vector_compare(:2, change_vector$$) = 1)) 
and rownum = 1
SELECT /*+ NO_MERGE(DL$) ROWID(MAS$) ORDERED USE_NL(MAS$) NO_INDEX(MAS$) PQ_DISTRIBUTE(MAS$,RANDOM,NONE) */ 
COUNT(*) cnt  
FROM ALL_SUMDELTA DL$, "HEMANT"."SOURCE_TABLE"  MAS$  
WHERE DL$.TABLEOBJ# = :1 AND DL$.TIMESTAMP > :2 AND DL$.TIMESTAMP <= :3 
AND  MAS$.ROWID BETWEEN DL$.LOWROWID AND DL$.HIGHROWID
select dmltype$$, count(*) cnt from "HEMANT"."MLOG$_SOURCE_TABLE"  
where snaptime$$ > :1 and snaptime$$ <= :2  
group by dmltype$$  order by dmltype$$
delete from "HEMANT"."MLOG$_SOURCE_TABLE" 
where snaptime$$ <= :1
and this being the refresh (merge update) of the target MV
DELETE FROM "HEMANT"."MV_OF_SOURCE" SNAP$ 
WHERE "ID" IN 
(SELECT * FROM (SELECT MLOG$."ID" 
  FROM "HEMANT"."MLOG$_SOURCE_TABLE" MLOG$ 
  WHERE "SNAPTIME$$" > :1 AND ("DMLTYPE$$" != 'I')) 
  AS OF SNAPSHOT(:B_SCN) )
/* MV_REFRESH (MRG) */ MERGE INTO "HEMANT"."MV_OF_SOURCE" "SNA$" USING 
(SELECT * FROM (SELECT CURRENT$."ID",CURRENT$."DATA_ELEMENT_1",CURRENT$."DATA_ELEMENT_2",CURRENT$."DATE_COL" 
FROM (SELECT "SOURCE_TABLE"."ID" "ID","SOURCE_TABLE"."DATA_ELEMENT_1" "DATA_ELEMENT_1","SOURCE_TABLE"."DATA_ELEMENT_2" "DATA_ELEMENT_2","SOURCE_TABLE"."DATE_COL" "DATE_COL" 
FROM "SOURCE_TABLE" "SOURCE_TABLE") CURRENT$, 
(SELECT DISTINCT MLOG$."ID" FROM "HEMANT"."MLOG$_SOURCE_TABLE" MLOG$ WHERE "SNAPTIME$$" > :1 
AND ("DMLTYPE$$" != 'D')) LOG$ WHERE CURRENT$."ID" = LOG$."ID") AS OF SNAPSHOT(:B_SCN) )"AV$" ON ("SNA$"."ID" = "AV$"."ID") 
WHEN MATCHED THEN UPDATE  SET "SNA$"."DATA_ELEMENT_1" = "AV$"."DATA_ELEMENT_1","SNA$"."DATA_ELEMENT_2" = "AV$"."DATA_ELEMENT_2","SNA$"."DATE_COL" = "AV$"."DATE_COL" 
WHEN NOT MATCHED THEN INSERT  (SNA$."ID",SNA$."DATA_ELEMENT_1",SNA$."DATA_ELEMENT_2",SNA$."DATE_COL") 
VALUES (AV$."ID",AV$."DATA_ELEMENT_1",AV$."DATA_ELEMENT_2",AV$."DATE_COL")
So, we see a large number of intensive operations against the MLOG$ Materialized View Log object.
And on the MV, there is a DELETE followed by a MERGE (UPDATE/IINSERT)
Two takeaways :
1. Updating the Source Table of a Materialized View can have noticeable overheads
2. Refreshing a Materialized View takes some effort on the part of the database
(Did you notice the strange year 2100 date in the update of the MLOG$ table?
.
.
.
.
.
.
No comments:
Post a Comment