2012-03-21 20 views
6

Mam martwą danych opanowaną przez naszą bazę danych OLTP Oracle przy użyciu podstawowych Materialized Views z możliwością szybkiego odświeżania na żądanie. Odśwież działa dobrze. Interesujące jest dodanie niektórych statystyk dotyczących odświeżania każdego zmaterializowanego widoku, takich jak liczba wstawek, aktualizacji i usunięć, które zostały zastosowane do tabeli głównej od czasu ostatniego odświeżenia, które można znaleźć w user_tab_modifications. Czy jest to możliwe w przypadku zmaterializowanych widoków?Widok zmaterializowany: jak mogę znaleźć liczbę aktualizacji, wstawień i usunięć zastosowanych podczas odświeżania?

Odpowiedz

6

Przed wykonaniem odświeżania można wykonać kwerendę w dzienniku zmaterializowanego widoku, aby zobaczyć, jakie rodzaje wektorów zmian przechowuje. Będą to wektory zmian, które należy zastosować do zmaterializowanego widoku podczas procesu odświeżania (zakładając, że istnieje tylko jeden zmaterializowany widok, który zależy od tego zmaterializowanego dziennika widoku).

Na przykład, jeśli utworzę swój stół, mój zmaterializowany dziennik widoku i mój zmaterializowany widok.

SQL> create table foo(col1 number primary key); 

Table created. 

SQL> create materialized view log on foo; 

Materialized view log created. 


SQL> ed 
Wrote file afiedt.buf 

    1 create materialized view mv_foo 
    2 refresh fast on demand 
    3 as 
    4 select * 
    5* from foo 
SQL>/

Materialized view created. 

SQL> insert into foo values(1); 

1 row created. 

SQL> insert into foo values(2); 

1 row created. 

SQL> commit; 

Commit complete. 

Teraz odświeżenie zmaterializowanej widok i upewnij się, że tabela i zmaterializował widok są zsynchronizowane

SQL> exec dbms_mview.refresh('MV_FOO'); 

PL/SQL procedure successfully completed. 

SQL> select * from user_tab_modifications where table_name = 'MV_FOO'; 

no rows selected 

SQL> select * from foo; 

     COL1 
---------- 
     1 
     2 

SQL> select * from mv_foo; 

     COL1 
---------- 
     1 
     2 

Ponieważ oba obiekty są zsynchronizowane, logu widoku zmaterializowanego jest pusta (zmaterializowanej widok dziennika zostanie nazwany MLOG$_<<table name>>

SQL> select * from mlog$_foo; 

no rows selected 

teraz, jeśli wstawić nowy wiersz do tabeli, zobaczymy wiersza w widoku zmaterializowanego z DMLTYPE$$ z I wskazujący INSERT

SQL> insert into foo values(3); 

1 row created. 

SQL> select * from mlog$_foo; 

     COL1 SNAPTIME$ D O 
---------- --------- - - 
CHANGE_VECTOR$$ 
-------------------------------------------------------------------------------- 
    XID$$ 
---------- 
     3 01-JAN-00 I N 
FE 
2.2519E+15 

Więc można zrobić coś takiego, aby uzyskać liczbę oczekujących wkładki, aktualizacje i usuwa.

SELECT SUM(CASE WHEN dmltype$$ = 'I' THEN 1 ELSE 0 END) num_pending_inserts, 
     SUM(CASE WHEN dmltype$$ = 'U' THEN 1 ELSE 0 END) num_pending_updates, 
     SUM(CASE WHEN dmltype$$ = 'D' THEN 1 ELSE 0 END) num_pending_deletes 
    FROM mlog$_foo 

Po odświeżeniu zmaterializowanego dziennika widoku ta informacja już jednak nie istnieje.

Z drugiej strony, USER_TAB_MODIFICATIONS powinien śledzić przybliżoną liczbę zmian, które zostały wprowadzone do zmaterializowanej widzenia, ponieważ po raz ostatni, że statystyki zostały zebrane na nim tak jak byłoby śledzić informacje o tabeli. Prawie na pewno trzeba będzie zadzwonić pod numer DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO, aby wymusić udostępnienie danych, jeśli chcesz przechwycić dane przed i po odświeżeniu zmaterializowanego widoku.

SELECT inserts, updates, deletes 
    INTO l_starting_inserts, 
     l_starting_updates, 
     l_starting_deletes 
    FROM user_tab_modifications 
WHERE table_name = 'MV_FOO'; 

dbms_mview.refresh('MV_FOO'); 
dbms_stats.flush_database_monitoring_info; 

SELECT inserts, updates, deletes 
    INTO l_ending_inserts, 
     l_ending_updates, 
     l_ending_deletes 
    FROM user_tab_modifications 
WHERE table_name = 'MV_FOO'; 

l_incremental_inserts := l_ending_inserts - l_starting_inserts; 
l_incremental_updates := l_ending_updates - l_starting_updates; 
l_incremental_deletes := l_ending_deletes - l_starting_deletes; 
+0

Dziękuję za tę bardzo dogłębną odpowiedź! – user1284595