探討實體化視圖的重新整理機制

來源:互聯網
上載者:User
視圖|重新整理
探討實體化視圖的重新整理機制

 

Author:Kamus

Mail:kamus@itpub.net

Date:2004年10月

 

今天給客戶搭建曆史查詢服務器,用oracle8i的snapshot實現,也就是9i的實體化視圖。

順手做了一下trace,看了一下重新整理時候oracle後台是怎麼工作的。

 

 

前期準備,使用DBMS_SUPPORT包,這個包預設是沒有安裝的,需要運行下面的命令來手動安裝。

SQL>conn / as sysdba

SQL>@?\rdbms\admin\dbmssupp.sql

SQL>GRANT execute ON dbms_support TO kamus;

SQL>CREATE PUBLIC SYNONYM dbms_support FOR dbms_support;

 

先看快速重新整理,測試表是T1,建立了快照日誌,用於重新整理的視圖是MV_T1,使用者是KAMUS

執行trace:

SQL>conn kamus

SQL>exec dbms_support.start_trace(waits=>TRUE,binds=>TRUE);

SQL>exec dbms_mview.refresh(list => 'MV_T1');

SQL>exec dbms_support.stop_trace;

 

然後tkprof產生trace結果的報表,下面只是節選了其中一部分。

執行一次dbms_mview.refresh,Oracle後台會執行13個 user  SQL和92個 internal SQL,實在是一個繁雜的工作。

 

1。開始重新整理

BEGIN dbms_mview.refresh(list => 'MV_T1'); END;

 

2。檢查SNAP$表,確認目前使用者是否有需要重新整理的視圖

 

3。在DBMS_LOCK_ALLOCATED資料字典中更新記錄,設定到期時間

UPDATE DBMS_LOCK_ALLOCATED SET EXPIRATION = SYSDATE + (:B1 /86400)

WHERE

 ROWID = :B2

 

4。檢查可能會用到的dblink和一些進階隊列的資料字典

5。檢查表的相關約束

 

6。檢查幾個初始化參數的值,包括_enable_refresh_schedule,_delay_index_maintain,compatible

 

7。將MLOG中所有沒有標誌為定時重新整理的記錄更新為立刻重新整理

update "KAMUS"."MLOG$_T1" set snaptime$$ = :1 

where

 snaptime$$ > to_date('2100-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS')

 

8。重新編譯MV_T1實體化視圖

ALTER SUMMARY "KAMUS"."MV_T1" COMPILE

這一步比較可疑,SQL中是沒有alter summary找個命令的,如果是編譯的話,那麼就可能鎖定對象,就有可能產生library cache lock

 

9。檢查要執行的SQL文,這一步比較有趣

SELECT operation#, cols, sql_txt, tabnum, fcmaskvec, ejmaskvec, setnum  

FROM

 sys.snap_refop$   WHERE ((operation# >= 0 AND operation# <= 6) OR operation#

  IN (10, 12, 13))   AND sowner = :1 AND vname = :2 AND instsite = :3   ORDER

  BY tabnum, setnum, operation#

對於一個MV重新整理將會使用到SQL全部存在這張表中。

如果是fast重新整理,那麼對於查詢mlog表,查詢基表的資料,insert、update、delete實體化視圖都分別有一句SQL。

其中operation#欄位值的常見含義如下:

0:查詢mlog表

1:對於實體化視圖的delete操作

2:查詢基表的最新資料

3:對於實體化視圖的update操作

4:對於實體化視圖的insert操作

如果是complete重新整理,那麼只有一條記錄,是基於基表的全表insert操作,operation#是7。

此處的執行計畫顯示是對於snap_refop$的全表掃描,如果系統中存在大量需要refresh的實體化視圖,無疑是影響效能的。

 

10。取得需要更新的記錄主鍵

SELECT DISTINCT LOG$."IDATE"

FROM

 (SELECT MLOG$."IDATE" FROM "KAMUS"."MLOG$_T1" MLOG$ WHERE "SNAPTIME$$" > :1

  AND ("DMLTYPE$$" != 'I')) LOG$ WHERE (LOG$."IDATE") NOT IN (SELECT

MAS_TAB$."IDATE" FROM "T1" "MAS_TAB$" WHERE LOG$."IDATE" = MAS_TAB$."IDATE")

注意到這裡使用了distinct,也就是我們可以猜測,如果在一次重新整理之前對於同一條記錄作了多次的修改,那麼重新整理操作只需要作一次,就是獲得基表中該條記錄的最新值就可以了。

IDATE欄位是我的測試表中的主鍵。

"DMLTYPE$$" != 'I'表示不是insert的操作。

此處的執行計畫顯示對於mlog表進行了一次全表掃描,如果有大量的更新操作,無疑又是影響效能的一步。

 

11。取得基表中當前需要重新整理的記錄所有欄位的最新值

SELECT CURRENT$."IDATE",CURRENT$."C"

FROM

 (SELECT "T1"."IDATE" "IDATE","T1"."C" "C" FROM "T1" "T1") CURRENT$, (SELECT

  DISTINCT MLOG$."IDATE" FROM "KAMUS"."MLOG$_T1" MLOG$ WHERE "SNAPTIME$$" >

:1 AND ("DMLTYPE$$" != 'D')) LOG$ WHERE CURRENT$."IDATE" = LOG$."IDATE"

這一步動作表示,mlog中只儲存修改操作涉及到的記錄主鍵,其它的欄位值仍然會到基表中去作查詢。

此處的執行計畫顯示對於mlog表再一次作了全表掃描。

 

12。用取得的最新值更新實體化視圖

UPDATE "KAMUS"."MV_T1" SET "IDATE" = :1,"C" = :2

WHERE

 "IDATE" = :1

這一步仍然比較奇怪,因為我的測試中只作了insert,並沒有update的操作,莫非oracle在重新整理時,並不管是否存在update的操作,都會例行作一次視圖資料的更新?不過此處更新會使用實體化視圖中的主鍵,速度應該時很快的。

 

13。將取得的最新值插入到實體化視圖中

INSERT INTO "KAMUS"."MV_T1"  ("IDATE","C")

VALUES

 (:1,:2)

這步才到了真正要實現的目的上,呵呵。

 

14。更新一批資料字典,表明重新整理已經完成

 

15。刪除mlog表中已經重新整理過的記錄

delete from "KAMUS"."MLOG$_T1"

where

 snaptime$$ <= :1

這一步操作是比較耗費資源的,使用delete,產生redo和undo,無法降低mlog表的HWM標誌,同時又是一次全表掃描,如果經常有大量更新發生,最好能定時作mlog表的truncate動作,否則這一步操作可能會越來越慢。

 

至此,一次實體化視圖的快速重新整理算是完全結束了。

 

我們繼續看一下完全重新整理的後台機制。

1-8步跟快速重新整理基本相同。

9。檢查要執行的SQL文

SELECT operation#, cols, sql_txt

FROM

 sys.snap_refop$   WHERE operation# = 7 AND sowner = :1 AND vname = :2 AND

instsite = :3

可以看到直接去找operation# = 7的SQL了,這就是完全重新整理需要使用的SQL。

 

10。檢查完全重新整理涉及到的約束,索引,觸發器

 

11。刪除實體化視圖中的原有資料

delete from "KAMUS"."MV_T"

這一步讓我很詫異,記得文檔中說應該是truncate操作,但是此處顯示的是delete?這樣的話,完全重新整理的代價實在是很大了。

 

12。插入基表中所有資料

INSERT /*+ BYPASS_RECURSIVE_CHECK */ INTO "KAMUS"."MV_T"("X") SELECT "T"."X"

FROM "T" "T"

這裡使用到的提示/*+ BYPASS_RECURSIVE_CHECK */,是不是在實際應用中可以提高INSERT的效率呢?

 

13。更新一批資料字典,表明重新整理已經完成

 

14。如果在基表上建立了重新整理日誌mlog表,那麼Oracle不管這次重新整理是不是完全重新整理,都會去作一次刪除mlog表中資料的操作。如果沒有建立過mlog,那麼這一步將被省略。所以如果決定使用完全重新整理,那麼就不要在基表上建立重新整理日誌了,省得無謂的資源消耗。

 


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。