1、物化視圖的通常用法物化視圖是一種特殊的物理表,「物化」(Materialized)視圖是相對普通視圖而言的。普通視圖是虛擬表,應用的侷限性大,任何對視圖的查詢,Oracle都實際上轉換爲視圖SQL語句的查詢。這樣對總體查詢性能的提升,並無實質上的好處。 一、物化視圖的類型ON DEMAND、ON COMMIT。兩者的區別在於刷新方法的不一樣,ON DEMAND顧名思義,僅在該物化視圖「須要」被刷新了,才進行刷新(REFRESH),即更新物化視圖,以保證和基表數據的一致性;而ON COMMIT是說,一旦基表有了COMMIT,即事務提交,則馬上刷新,馬上更新物化視圖,使得數據和基表一致。 物化視圖能夠分爲如下三種類型:包含彙集的物化視圖;只包含鏈接的物化視圖;嵌套物化視圖。三種物化視圖的快速刷新的限制條件有很大區別,而對於其餘方面則區別不大。建立物化視圖時能夠指定多種選項,下面對幾種主要的選擇進行簡單說明: 建立方式(Build Methods):包括BUILD IMMEDIATE和BUILD DEFERRED兩種。BUILD IMMEDIATE是在建立物化視圖的時候就生成數據,而BUILD DEFERRED則在建立時不生成數據,之後根據須要在生成數據。默認爲BUILD IMMEDIATE。 查詢重寫(Query Rewrite):包括ENABLE QUERY REWRITE和DISABLE QUERY REWRITE兩種。分別指出建立的物化視圖是否支持查詢重寫。查詢重寫是指當對物化視圖的基表進行查詢時,Oracle會自動判斷可否經過查詢物化視圖來獲得結果,若是能夠,則避免了彙集或鏈接操做,而直接從已經計算好的物化視圖中讀取數據。默認爲DISABLE QUERY REWRITE。 在創建物化視圖的時候能夠指定ORDER BY語句,使生成的數據按照必定的順序進行保存。不過這個語句不會寫入物化視圖的定義中,並且對之後的刷新也無效。 二、ON DEMAND物化視圖物化視圖的建立自己是很複雜和須要優化參數設置的,特別是針對大型生產數據庫系統而言。但Oracle容許以這種最簡單的,相似於普通視圖的方式來作,因此不可避免的會涉及到默認值問題。也就是說Oracle給物化視圖的重要定義參數的默認值處理是咱們須要特別注意的。物化視圖的特色: (1) 物化視圖在某種意義上說就是一個物理表(並且不只僅是一個物理表),這經過其能夠被user_tables查詢出來,而獲得佐證; (2) 物化視圖也是一種段(segment),因此其有本身的物理存儲屬性; (3) 物化視圖會佔用數據庫磁盤空間,這點從user_segment的查詢結果,能夠獲得佐證; 建立語句: SQL> create materialized view mv_name as select * from table_name; 默認狀況下,若是沒指定刷新方法和刷新模式,則Oracle默認爲FORCE和DEMAND。 物化視圖的數據怎麼隨着基表而更新? Oracle提供了兩種方式,手工刷新和自動刷新,默認爲手工刷新。也就是說,經過咱們手工的執行某個Oracle提供的系統級存儲過程或包,來保證物化視圖與基表數據一致性。這是最基本的刷新辦法了。自動刷新,其實也就是Oracle會創建一個job,經過這個job來調用相同的存儲過程或包,加以實現。 ON DEMAND物化視圖的特性及其和ON COMMIT物化視圖的區別,即前者不刷新(手工或自動)就不更新物化視圖,然後者不刷新也會更新物化視圖,——只要基表發生了COMMIT。 建立定時刷新的物化視圖(指定物化視圖天天刷新一次): SQL> create materialized view mv_name refresh force on demand start with sysdate next sysdate+1; 上述建立的物化視圖天天刷新,可是沒有指定刷新時間,若是要指定刷新時間(好比天天晚上10:00定時刷新一次): SQL> create materialized view mv_name refresh force on demand start with sysdate next to_date( concat( to_char( sysdate+1,'dd-mm-yyyy'),' 22:00:00'),'dd-mm-yyyy hh24:mi:ss'); 三、ON COMMIT物化視圖ON COMMIT物化視圖的建立,和上面建立ON DEMAND的物化視圖區別不大。由於ON DEMAND是默認的,因此ON COMMIT物化視圖,須要再增長個參數便可。 須要注意的是,沒法在定義時僅指定ON COMMIT,還得附帶個參數才行。建立ON COMMIT物化視圖: SQL> create materialized view mv_name refresh force on commit as select * from table_name; 備註:實際建立過程當中,基表須要有主鍵約束,不然會報錯(ORA-12014)。 四、物化視圖的刷新刷新(Refresh):指當基表發生了DML操做後,物化視圖什麼時候採用哪一種方式和基表進行同步。 刷新的模式有兩種:ON DEMAND和ON COMMIT。 刷新的方法有四種:FAST、COMPLETE、FORCE和NEVER。FAST刷新採用增量刷新,只刷新自上次刷新之後進行的修改。COMPLETE刷新對整個物化視圖進行徹底的刷新。若是選擇FORCE方式,則Oracle在刷新時會去判斷是否能夠進行快速刷新,若是能夠則採用FAST方式,不然採用COMPLETE的方式。NEVER指物化視圖不進行任何刷新。 對於已經建立好的物化視圖,能夠修改其刷新方式,好比把物化視圖mv_name的刷新方式修改成天天晚上10點刷新一次: SQL> alter materialized view mv_name refresh force on demand start with sysdate next to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),' 22:00:00'),'dd-mm-yyyy hh24:mi:ss'); 五、物化視圖日誌若是須要進行快速刷新,則須要創建物化視圖日誌。物化視圖日誌根據不一樣物化視圖的快速刷新的須要,能夠創建爲ROWID或PRIMARY KEY類型的。還能夠選擇是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。 能夠指明ON PREBUILD TABLE語句將物化視圖創建在一個已經存在的表上。這種狀況下,物化視圖和表必須同名。當刪除物化視圖時,不會刪除同名的表。這種物化視圖的查詢重寫要求參數QUERY_REWRITE_INTEGERITY必須設置爲trusted或者stale_tolerated。 六、物化視圖分區並且基於分區的物化視圖能夠支持分區變化跟蹤(PCT)。具備這種特性的物化視圖,當基表進行了分區維護操做後,仍然能夠進行快速刷新操做。對於彙集物化視圖,能夠在GROUP BY列表中使用CUBE或ROLLUP,來創建不一樣等級的彙集物化視圖。 2、物化視圖與數據遷移Oracle 的物化視圖提供了強大的功能,能夠用於預先計算並保存錶鏈接或彙集等耗時較多的操做的結果,這樣,在執行查詢時,就能夠避免進行這些耗時的操做,而從快速的獲得結果。物化視圖有不少方面和索引很類似:使用物化視圖的目的是爲了提升查詢性能;物化視圖對應用透明,增長和刪除物化視圖不會影響應用程序中SQL 語句的正確性和有效性;物化視圖須要佔用存儲空間;當基表發生變化時,物化視圖也應當刷新。 如如何創建在特定的表空間上,這些在其餘的物化視圖上面幾乎都沒有任何介紹的。主要以我作的一個例子來操做,若是對物化視圖的基本概念清楚了就比較明白在那裏寫特定的表空間存儲了。 一、簡單試驗在master site上建立表和mview log SQL> create table stu (id varchar2(10) primary key ,name varchar2(20)); Table created. SQL> create materialized view log on stu; Materialized view log created. 在mv site上建立mview SQL> create materialized view stu_mv refresh fast start with sysdate next sysdate+1/1440 with primary key as select * from stu@to_vm9; Materialized view created. SQL> select job,log_user,last_date,last_sec,next_date,next_sec,interval,what from user_jobs; JOB LOG_USER LAST_DATE LAST_SEC NEXT_DATE NEXT_SEC INTERVAL WHAT --- --------- ----------- --------- ----------- ---------- -------------- ----------------------------------------- 21 SEAGULL 2008-2-18 1 14:41:43 2008-2-18 1 14:42:43 sysdate+1/1440 dbms_refresh.refresh('"SEAGULL"."STU_MV"'); SQL> select * from tab; TNAME TABTYPE CLUSTERID ------------------------------ ------- ---------- STU_MV TABLE 在master site上對master table作更新: SQL> INSERT INTO STU(ID,NAME) VALUES('56','555555555555'); 1 row created. SQL> commit; 等1分鐘後在mv site上檢查 SQL> select * from stu_mv; ID NAME ---------- -------------------- 56 555555555555 二、跨版本數據遷移利用prebuilt mv實現跨平臺,跨版本數據遷移。該方法的實現原理是對於要遷移的表對象,須要有一個主鍵,用於mv的刷新,對於符合該要求的表,在源表上建立mv日誌,再在目標數據庫上建立結構同樣的表,而後在目標表上採用prebuilt方式建立mv,第一次採用徹底刷新,以後採用增量刷新,等真正要切換的時候,只須要刷新完增量的日誌,刪除mv,保留目標表便可。基本思路的例子: 在源庫上建立表和mview log SQL> create table big_t1 as select * from dba_objects; Table created. SQL> select count(1) from big_t1; COUNT(1) ---------- 6170 SQL> create materialized view log on big_t1; Materialized view log created. 在目標數據庫上建立與該表同樣的表,並在該表上建立prebuilt mv: SQL> create table big_t1 as select * from big_t1@to_vm9 where 1=2; Table created. SQL> select count(1) from big_t1; COUNT(1) ---------- 0 SQL> create materialized view big_t1 on prebuilt table refresh fast as select * from big_t1@to_vm9; Materialized view created. 作徹底刷新和增量刷新 SQL> exec dbms_mview.refresh('BIG_T1','Complete'); PL/SQL procedure successfully completed. SQL> select count(1) from big_t1; COUNT(1) ---------- 6170 此時模擬在作徹底刷新過程當中,源庫的表又發生了變化 SQL> insert into big_t1(object_id,owner) values(99991,'test'); 1 row created. SQL> commit; Commit complete. 再作增量刷新 SQL> select count(1) from big_t1; COUNT(1) ---------- 6170 SQL> exec dbms_mview.refresh('BIG_T1'); PL/SQL procedure successfully completed. SQL> select count(1) from big_t1; COUNT(1) ---------- 6171 停機切換,作最後一次刷新,而後刪除源庫的mview log和目標庫的mview: SQL> exec dbms_mview.refresh('BIG_T1'); PL/SQL procedure successfully completed. SQL> drop materialized view big_t1; Materialized view dropped. SQL> select count(1) from big_t1; COUNT(1) ---------- 6171 這裏刪除的mview(big_t1)是prebuilt mv,因此刪除該mview,並不刪除相應的表。若是刪除了mvnew(stu_mv),因爲是普通mv,則刪除了該mview,就沒有對應的表了。 SQL> drop materialized view stu_mv; Materialized view dropped. SQL> select * from tab; TNAME TABTYPE CLUSTERID ------------------------------ ------- ---------- BIG_T1 TABLE 三、建立存儲的日誌空間 SQL> CREATE MATERIALIZED VIEW LOG ON mv_lvy_levytaxbgtdiv tablespace ZGMV_DATA --日誌保存在特定的表空間 WITH ROWID ; SQL> CREATE MATERIALIZED VIEW LOG ON tb_lvy_levydetaildata tablespace ZGMV_DATA --日誌保存在特定的表空間 WITH ROWID,sequence(LEVYDETAILDATAID); SQL> CREATE MATERIALIZED VIEW LOG ON tb_lvy_levydata tablespace ZGMV_DATA --日誌保存在特定的表空間 WITH rowid,sequence(LEVYDATAID); 四、而後建立物化視圖SQL> create materialized view MV_LVY_LEVYDETAILDATA TABLESPACE ZGMV_DATA --保存表空間 BUILD DEFERRED --延遲刷新不當即刷新 refresh force --若是能夠快速刷新則進行快速刷新,不然徹底刷新 on demand --按照指定方式刷新 start with to_date('24-11-2005 18:00:10', 'dd-mm-yyyy hh24:mi:ss') --第一次刷新時間 next TRUNC(SYSDATE+1)+18/24 --刷新時間間隔 as SELECT levydetaildataid, detaildatano, taxtermbegin, taxtermend, ...... ROUND(taxdeduct * taxpercent1, 2) - ROUND(taxdeduct * taxpercent2, 2) - ROUND(taxdeduct * taxpercent3, 2) - ROUND(taxdeduct * taxpercent4, 2) - ROUND(taxdeduct * taxpercent5, 2) taxdeduct, ROUND(taxfinal * taxpercent1, 2) - ROUND(taxfinal * taxpercent2, 2) - ROUND(taxfinal * taxpercent3, 2) - ROUND(taxfinal * taxpercent4, 2) - ROUND(taxfinal * taxpercent5, 2) taxfinal, a.levydataid, a.budgetitemcode, taxtypecode, ...... FROM tb_lvy_levydetaildata a, tb_lvy_levydata c, MV_LVY_LEVYTAXBGTDIV b WHERE a.levydataid = c.levydataid AND a.budgetdistrscalecode = b.budgetdistrscalecode AND a.budgetitemcode = b.budgetitemcode AND c.incomeresidecode = b.rcvfisccode AND C.TAXSTATUSCODE='08' AND C.NEGATIVEFLAG!='9' 五、刪除物化視圖日誌物化視圖日誌常常會因爲物化視圖長時間沒有刷新,或者基表的一次批量數據更改而變得很大,這會影響物化視圖的刷新性能,所以對於這種狀況須要對物化視圖日誌進行處理,下降物化視圖日誌表的高水位線。 物化視圖日誌會記錄下基表全部的增、刪、改操做,而物化視圖執行完快速刷新操做後,會從物化視圖日誌中將本物化視圖刷新過且其餘物化視圖所不須要刷新的記錄刪除掉。若是其中一個物化視圖一直不刷新,那麼物化視圖日誌就會變得愈來愈大。 還有一種狀況,好比表中插入了大量的數據,或者刪除了大量的數據,或者將表中的某一列統一更新爲一個值,這種操做都會在物化視圖日誌中產生大量的記錄。 而物化視圖日誌的增大必然影響物化視圖的刷新速度。一方面,物化視圖在刷新的時候要掃描物化視圖日誌,另外一方面,物化視圖在刷新介紹後,也要清除物化視圖日誌中的記錄,仍然要掃描物化視圖日誌,所以物化視圖日誌的大小直接會影響物化視圖快速刷新的速度。更重要的是,物化視圖日誌的高水位一旦增加到一個很高的位置,即便之後物化視圖日誌中記錄不多,甚至沒有記錄存在,物化視圖在刷新的時候仍然須要較長的時間。 SQL> DROP materialized view log on mv_lvy_levytaxbgtdiv; SQL> DROP materialized view log on tb_lvy_levydetaildata; SQL> DROP materialized view log on tb_lvy_levydata; 六、刪除物化視圖SQL> drop materialized view MV_LVY_LEVYDETAILDATA; 基本和對錶的操做一致,物化視圖因爲是物理真實存在的,故能夠建立索引,建立方式和對普通表建立方式相同。 3、ORACLE物化視圖總結物化視圖是包括一個查詢結果的數據庫對像,它是遠程數據的的本地副本,或者用來生成基於數據表求和的彙總表。物化視圖存儲基於遠程表的數據,也能夠稱爲快照。物化視圖能夠查詢表,視圖和其它的物化視圖。主要用在數據倉庫和決策支持系統。 一般狀況下,物化視圖被稱爲主表(在複製期間)或明細表(在數據倉庫中)。對於複製,物化視圖容許你在本地維護遠程數據的副本,這些副本是隻讀的。若是你想修改本地副本,必須用高級複製的功能。當你想從一個表或視圖中抽取數據時,你能夠用從物化視圖中抽取。對於數據倉庫,建立的物化視圖一般狀況下是聚合視圖,單一表聚合視圖和鏈接視圖。 物化視圖把他的物理結構存儲在本身的段中,該段能夠被索引和分區。查詢沒必要徹底匹配用來建立物化視圖的SQL語句,優化程序能夠動態重寫一個與原定義相近的查詢,以便物化視圖用來代替實際的表,這種查詢重寫自動發生,對用戶是透明的。 一、使用物化視圖前的幾個配置步驟(1) 肯定那些語句要建立物化視圖。 (2) 決定是否要保持視圖與基礎表數據同步。 若是不一樣步,可選擇以下三種刷新方式: COMPLETE:刷新啓動時,先truncate物化視圖,再從基礎表從新插入填充數據。 FAST:只刷新基礎表上次刷新後改變的數據。使用視圖的日誌數據或ROWID完成。 FORCE:默認的方式。先使用FAST,不行就使用COMPLETE方式。 (3) 設置init.ora的參數: JOB_QUEUE_PROCESSES,必須設置大於 1。 QUERY_REWRITE_ENABLED,設置爲TRUE時,容許動態重寫查詢。 QUERY_REWRITE_INTEGRITY,肯定訪問物化視圖時數據一致性要遵照的程度。 OPTIMIZER_MODE,必須設置成CBO的某種方式。 使用一個物化視圖,用戶只需在基礎表上擁有權限便可。 二、建立物化視圖SQL>create materialized view emp_by_district Tablespace mview_data Build immediate Refresh fast Enable query rewrite As Select d.id,count(e.last_name) from distributor dist,district d,employee e Where e.id = dist.manager_id And d.id dist.district_id Group by d.id; 如下是Oracle建立物化視圖時的經常使用語法,各參數的含義以下: 一、refresh [fast|complete|force] 視圖刷新的方式 fast: 增量刷新.假設前一次刷新的時間爲t1,那麼使用fast模式刷新物化視圖時,只向視圖中添加t1到當前時間段內,主表變化過的數據.爲了記錄這種變化,創建增量刷新物化視圖還須要一個物化視圖日誌表。create materialized view log on (主表名)。 complete:所有刷新。至關於從新執行一次建立視圖的查詢語句。 force: 這是默認的數據刷新方式。當可使用fast模式時,數據刷新將採用fast方式;不然使用complete方式。 二、MV數據刷新的時間 on demand:在用戶須要刷新的時候刷新,這裏就要求用戶本身動手去刷新數據了(也可使用job定時刷新) on commit:當主表中有數據提交的時候,當即刷新MV中的數據; start ……:從指定的時間開始,每隔一段時間(由next指定)就刷新一次; 三、Build immediate一共有三個選項 (1) Build immediate:創建物化視圖,並使用當前命令執行的數據立刻填充視圖數據。 (2) Build deferred:只創建物化視圖,在第一次刷新之間不填充數據。 (3) No prebuilt table,使用事先已存在的,已含有視圖定義中有現有數據的表,而不是創建一個新結構來保存數據。 若是是refresh fast on commit或refresh complete on commit建立的,則在基礎表提交的時候都會獲得刷新。啓用或禁用物化視圖,須要有query rewrite或global query rewrite權限。 三、刷新物化視圖自動刷新: (1) 使用commit選項。 (2) 使用dbms_mview安排自動刷新時間。 手工刷新: SQL>execute dbms_mview.refresh(‘EMP_BY_DISTRICT’); --刷新指定的物化視圖 SQL>execute dbms_mview.refresh_defresh_dependent(‘EMPLOYEE’); ――刷新利用了該表的全部物化視圖 SQL>execute dbms_mview.refresh_all_mviews; ――刷新該模式中,自上次刷新以來,未獲得刷新的全部物化視圖。 四、禁用物化視圖- 修改init.ora參數的query_rewrite_enabled參數設置成flase,重啓實例。 - 使用alter system set query_rewrite_enabled = flase;動態修改。 - 使用alter session set query_rewrite_enabled = flash;修改會話內。 - 使用 norewrite提示。 五、刪除物化視圖SQL>drop materialized view emp_by_district; |