Oracle物化視圖:創建最簡單物化視圖

物化視圖是Oracle令人激賞的功能之一,在OLAP和OLTP系統都有廣泛應用。本系列文章對其進行由淺入深的案例講解。本文側重在最簡單的ON DEMAND和ON COMMIT物化視圖的討論。

     【IT專家網獨家】 

      物化視圖是一種特殊的物理表,“物化”(Materialized)視圖是相對普通視圖而言的。普通視圖是虛擬表,應用的侷限性大,任何對視圖的查詢,Oracle都實際上轉換爲視圖SQL語句的查詢。這樣對整體查詢性能的提高,並沒有實質上的好處。

  Oracle最早在OLAP系統中引入了物化視圖的概念。但後來很多大型OLTP系統中,發現類似統計的查詢是無可避免,而這些查詢操作如果很頻繁,對整體數據庫性能是很致命的。於是Oracle開始不斷的改進物化視圖,使得其也開始合適OLTP系統。從Oracle 8i到現在,功能已經相對比較完備了。

  本文是Oracle物化視圖系列文章的第一篇,有兩個主要目的,來體驗一下創建ON DEMAND和ON COMMIT物化視圖的方法。ON DEMAND和ON COMMIT物化視圖的區別在於其刷新方法的不同,ON DEMAND顧名思義,僅在該物化視圖“需要”被刷新了,才進行刷新(REFRESH),即更新物化視圖,以保證和基表數據的一致性;而ON COMMIT是說,一旦基表有了COMMIT,即事務提交,則立刻刷新,立刻更新物化視圖,使得數據和基表一致。

  1、第一個ON DEMAND物化視圖

  1.1、創建ON DEMAND物化視圖

  下面創建一個最簡單的物化視圖,這個物化視圖的定義很類似於普通視圖的創建語句,只是多了一個materialized,但就是這個單詞,造成了物化視圖和普通視圖(虛擬表)的天壤之別,也引申出後面很多的事情,呵呵。

  本例中需要特別注意的是,Oracle給物化視圖的重要定義參數的默認值處理,在下面的例子中會有特別說明。因爲物化視圖的創建本身是很複雜和需要優化參數設置的,特別是針對大型生產數據庫系統而言。但Oracle允許以這種最簡單的,類似於普通視圖的辦法來做,所以不可避免的會涉及到默認值問題。

  像我們這樣,創建物化視圖時未作指定,則Oracle按ON DEMAND模式來創建。

  從下例中可以看出:

  1) 物化視圖在某種意義上說就是一個物理表(而且不僅僅是一個物理表),這通過其可以被user_tables查詢出來,而得到佐證;

  2) 物化視圖也是一種段(segment),所以其有自己的物理存儲屬性;

  3) 物化視圖會佔用數據庫磁盤空間,這點從user_segment的查詢結果,可以得到佐證。

  •    創建物化視圖

  --獲取數據庫rdbms版本信息  

      SQL> select * from v$version;
  BANNER
  --------------------------------------------------------------------------------
  Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
  PL/SQL Release 11.1.0.6.0 - Production
  CORE 11.1.0.6.0 Production
  TNS for 32-bit Windows: Version 11.1.0.6.0 - Production
  NLSRTL Version 11.1.0.6.0 – Production
--創建物化視圖  

      SQL> create materialized view mv_testcf
  2 as
  3 select * from xiaotg.testcf;
  Materialized view created

  --分析物化視圖,以獲得統計信息 

      SQL> analyze table xiaotg.mv_testcf compute statistics;
  Table analyzed

  --查看物化視圖的行數,發現和master表(TESTCF)一樣  

      SQL> select tl.table_name, tl.num_rows from user_tables tl where tl.table_name in ( 'TESTCF', 'MV_TESTCF' );
  TABLE_NAME NUM_ROWS
  ------------------------------ ----------
  MV_TESTCF 80000
  TESTCF 80000

  --查看物化視圖的存儲參數  

      SQL> col segment_name for a24
  SQL> select sg.segment_name, sg.bytes, sg.blocks from user_segments sg where sg.segment_name = 'MV_TESTCF';
  SEGMENT_NAME BYTES BLOCKS
  ------------------------ ---------- ----------
  MV_TESTCF 9437184 1152
  •    查看物化視圖關鍵定義

  --查看物化視圖的定義設置,請關注藍色字體部分。

  --這表明,默認情況下,如果沒指定刷新方法和刷新模式,則Oracle默認爲FORCE和DEMAND。

  --其他的集中刷新方法和刷新模式以後將分別予以介紹。

  SQL> select mv.* from user_mviews mv where mv.MVIEW_NAME = 'MV_TESTCF';

 (爲增加查詢結果的可讀性,下面進行了行列的互轉)

      OWNERXIAOTG
  MVIEW_NAMEMV_TESTCF
  CONTAINER_NAMEMV_TESTCF
  QUERY
  QUERY_LEN80
  UPDATABLEN
  UPDATE_LOG
  MASTER_ROLLBACK_SEG
  MASTER_LINK
  REWRITE_ENABLEDN                                         
  REWRITE_CAPABILITYGENERAL
  REFRESH_MODEDEMAND
  REFRESH_METHODFORCE
  BUILD_MODEIMMEDIATE
  FAST_REFRESHABLEDML
  LAST_REFRESH_TYPECOMPLETE
  LAST_REFRESH_DATE2008-9-9 15:02
  STALENESSFRESH
  AFTER_FAST_REFRESHFRESH
  UNKNOWN_PREBUILTN
  UNKNOWN_PLSQL_FUNCN
  UNKNOWN_EXTERNAL_TABLEN
  UNKNOWN_CONSIDER_FRESHN
  UNKNOWN_IMPORTN
  UNKNOWN_TRUSTED_FDN
  COMPILE_STATEVALID
  USE_NO_INDEXN
  STALE_SINCE
  NUM_PCT_TABLES0
  NUM_FRESH_PCT_REGIONS
  NUM_STALE_PCT_REGIONS

  1.2、測試ON DEMAND物化視圖的更新特性

  物化視圖最重要的功能和特性之一,就是其數據會隨着基表(或稱主表,master表,本例中爲TESTCF)的變化而變,基表數據增了,物化視圖數據會變多;基表數據刪了,物化視圖數據也會變少。

  但怎麼更新?或者說物化視圖的數據怎麼隨着基表而更新?Oracle提供了兩種方式,手工刷新和自動刷新,像我們這種,在物化視圖定義時,未作任何指定,那當然是默認的手工刷新了。也就是說,通過我們手工的執行某個Oracle提供的系統級存儲過程或包,來保證物化視圖與基表數據一致性。

  這是最基本的刷新辦法了。但所謂的自動刷新,其實也就是Oracle會建立一個job,通過這個job來調用相同的存儲過程或包,加以實現,這在本系列文章的第2篇會將以詳細闡述。

  下面將測試INSERT,UPDATE和DELETE的測試方法類似,大家有興趣的話,可以自己試一試。

  需要注意的是,下面暫不討論如何刷新ON DEMAND物化視圖,這是下一篇文章的內容。下面僅僅關注ON DEMAND物化視圖的特性及其和ON COMMIT物化視圖的區別,即前者不刷新(手工或自動)就不更新物化視圖,而後者不刷新也會更新物化視圖,——只要基表發生了COMMIT。

  •    在基表插入測試數據

  基表數據插入後,會發現,物化視圖並不會隨之更新。

  --檢查基表和物化視圖是否有80001這一行記錄。

    SQL> col id for a10;
  SQL> col name for a30;
  SQL> select * from xiaotg.testcf t where t.id = 80001 ;
  ID NAME
  ---------- ------------------------------
  SQL> select * from xiaotg.mv_testcf t where t.id = 80001 ;
  ID NAME
  ---------- ------------------------------

  --插入測試數據80001 

  --這時發現,基表有數據,但物化視圖並沒有 

      SQL> insert into xiaotg.testcf
  2 values ( 80001, 'xiaotg he he');
  1 row inserted
  SQL> commit;
  Commit complete

  1.2.2 測試物化視圖數據是否更新

  從下面的實驗可以看出,物化視圖數據不會更新,即使等上1分鐘、1小時、或者1天。

  關於如何使得ON DEMAND物化視圖數據被更新,參加本系列的第二篇文章哈:)  

      SQL> select * from xiaotg.testcf t where t.id = 80001 ;
  ID NAME
  ---------- ------------------------------
  80001 xiaotg he he
  SQL> select * from xiaotg.mv_testcf t where t.id = 80001 ;
  ID NAME
  ---------- ------------------------------
  SQL>

  2、第一個ON COMMIT物化視圖

  最簡單的ON COMMIT物化視圖的創建,和上面創建ON DEMAND的物化視圖區別不大。因爲ON DEMAND是默認的,所以ON COMMIT物化視圖,需要再增加個參數即可。

  2.1 創建ON COMMIT物化視圖

  •    創建物化視圖

  需要注意的是,無法在定義時僅指定ON COMMIT,還得附帶個參數才行,本例中附帶refresh force,關於這個參數的意思,以後將加以闡述。

  --創建ON COMMIT物化視圖

    SQL> create materialized view mv_testcf2
  2 refresh force on commit
  3 as
  4 select * from xiaotg.testcf;
  Materialized view created
  SQL>

  --分析物化視圖和基表  

      SQL> analyze table xiaotg.mv_testcf2 compute statistics;
  Table analyzed
  SQL> analyze table xiaotg.testcf compute statistics;
  Table analyzed

  --查看當前基表和物化視圖的行數  

      SQL> select tl.table_name, tl.num_rows from user_tables tl where tl.table_name in ( 'TESTCF', 'MV_TESTCF2' );
  TABLE_NAME NUM_ROWS
  ------------------------------ ----------
  MV_TESTCF2 80000
  TESTCF 80000
  •    查看物化視圖關鍵定義

  可以從DBA_MVIEWS中看出,刷新模式爲COMMIT,這也是它和上面ON DEMAND物化視圖的唯一區別。 

    SQL> select mv.* from user_mviews mv where mv.MVIEW_NAME = 'MV_TESTCF';

  (爲增加查詢結果的可讀性,下面進行了行列的互轉,且只顯示前三個關鍵列的)  

      REFRESH_MODECOMMIT
  REFRESH_METHODFORCE
  BUILD_MODEIMMEDIATE

  2.2 測試ON COMMIT物化視圖的更新特性

  ON COMMIT物化視圖會在基表一旦提交時,就會立刻更新物化視圖本身,而且一般僅在物化視圖數據也被更新後,基表數據纔會事實的提交。

  這意味着,這種模式可能會導致延遲基表數據的提交。。這點在下面的實驗中體現得很清楚。

  實驗中,對基表TESTCF,平常的COMMIT在0.01秒內可以完成,但在有了ON COMMIT視圖MV_TESTCF2後,居然要6秒。速度減低了很多倍。ON COMMIT視圖對基表的影響可見一斑。

  •    在基表中插入數據  


SQL> set timing on;
  SQL> insert into xiaotg.testcf ( id, name ) values ( 80002, ' xiaotg again he he ');
  1 row inserted
  Executed in 0.015 seconds
  SQL> commit;
  Commit complete
  Executed in 6.985 seconds
  SQL> select * from xiaotg.testcf where id = 80002;
  ID NAME
  --------------------------------- --------------------------------------------------------------------------------
  80002 xiaotg again he he
  Executed in 0 seconds
  SQL> col id for a10;
  SQL> col name for a40;
  SQL> select * from xiaotg.testcf where id = 80002;
  ID NAME
  ---------- ----------------------------------------
  80002 xiaotg again he he
  Executed in 0.016 seconds
  SQL> select * from xiaotg.mv_testcf2 where id = 80002;
  ID NAME
  ---------- ---------------------------------------- 
  80002 xiaotg again he he
  Executed in 0.031 seconds
  •    測試基表正常情況下的COMMIT速度  

      SQL> drop materialized view mv_testcf2;
  Materialized view dropped
  Executed in 1.984 seconds
  SQL>
  SQL>
  SQL> insert into xiaotg.testcf ( id, name ) values ( 80003, ' xiaotg again he he 3 ');
  1 row inserted
  Executed in 0 seconds
  SQL> commit;
  Commit complete
  Executed in 0 seconds
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章