Oracle-Materialized View解读
物化視圖概述
物化視圖(Materialized View)在9i以前的版本叫做快照(SNAPSHOT),從9i開始改名叫做物化視圖。
Oracle的物化視圖是包括一個(gè)查詢結(jié)果的數(shù)據(jù)庫對像,它是遠(yuǎn)程數(shù)據(jù)的的本地副本,或者用來生成基于數(shù)據(jù)表求和的匯總表。
物化視圖可以用于預(yù)先計(jì)算并保存表連接或聚集等耗時(shí)較多的操作的結(jié)果,這樣,在執(zhí)行查詢時(shí),就可以避免進(jìn)行這些耗時(shí)的操作,而從快速的得到結(jié)果。
物化視圖有很多方面和索引很相似:
- 使用物化視圖的目的是為了提高查詢性能;
- 物化視圖對應(yīng)用透明,增加和刪除物化視圖不會(huì)影響應(yīng)用程序中SQL語句的正確性和有效性;
- 物化視圖需要占用存儲(chǔ)空間;
- 當(dāng)基表發(fā)生變化時(shí),物化視圖也應(yīng)當(dāng)刷新。
物化視圖可以查詢表,視圖和其它的物化視圖。
物化視圖由于是物理真實(shí)存在的,故可以創(chuàng)建索引。
物化視圖分類
- 包含聚集的物化視圖;
- 只包含連接的物化視圖;
- 嵌套物化視圖。
三種物化視圖的快速刷新的限制條件有很大區(qū)別,而對于其他方面則區(qū)別不大。
創(chuàng)建方式 Build Methods
分為兩種:build immediate 和 build deferred,
build immediate是在創(chuàng)建物化視圖的時(shí)候就生成數(shù)據(jù)。
build deferred則在創(chuàng)建時(shí)不生成數(shù)據(jù),以后根據(jù)需要在生成數(shù)據(jù)。
如果不指定,則默認(rèn)為build immediate。
查詢重寫 Query Rewrite
包括 enable query rewrite 和 disable query rewrite 兩種,分別指出創(chuàng)建的物化視圖是否支持查詢重寫。
查詢重寫是指當(dāng)對物化視圖的基表進(jìn)行查詢時(shí),oracle會(huì)自動(dòng)判斷能否通過查詢物化視圖來得到結(jié)果,如果可以,則避免了聚集或連接操作,而直接從已經(jīng)計(jì)算好的物化視圖中讀取數(shù)據(jù)。
默認(rèn)為disable query rewrite。
刷新 Refresh
物化視圖有二種刷新模式
在創(chuàng)建時(shí)refresh mode是 on demand 還是 on commit。
on demand 顧名思義,僅在該物化視圖“需要”被刷新了,才進(jìn)行刷新(REFRESH),即更新物化視圖,以保證和基表數(shù)據(jù)的一致性;
on commit 提交觸發(fā),一旦基表有了commit,即事務(wù)提交,則立刻刷新,立刻更新物化視圖,使得數(shù)據(jù)和基表一致。一般用這種方法在操作基表時(shí)速度會(huì)比較慢。
對基表,平常的COMMIT在0.01秒內(nèi)可以完成,但在有了ON COMMIT視圖后,居然要6秒。速度減低了很多倍。ON COMMIT視圖對基表的影響可見一斑。
創(chuàng)建物化視圖時(shí)未作指定,則Oracle按 on demand 模式來創(chuàng)建。
設(shè)置REFRESH ON COMMIT的物化視圖不能訪問遠(yuǎn)端對象。
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view在建立物化視圖的時(shí)候可以指定ORDER BY語句,使生成的數(shù)據(jù)按照一定的順序進(jìn)行保存。不過這個(gè)語句不會(huì)寫入物化視圖的定義中,而且對以后的刷新也無效。
如何刷新,則有三種刷新方法
完全刷新(COMPLETE):
會(huì)刪除表中所有的記錄(如果是單表刷新,可能會(huì)采用TRUNCATE的方式),然后根據(jù)物化視圖中查詢語句的定義重新生成物化視圖。
快速刷新(FAST):
采用增量刷新的機(jī)制,只將自上次刷新以后對基表進(jìn)行的所有操作刷新到物化視圖中去。FAST必須創(chuàng)建基于主表的視圖日志。對于增量刷新選項(xiàng),如果在子查詢中存在分析函數(shù),則物化視圖不起作用。
FORCE方式(默認(rèn)方式)
這是默認(rèn)的數(shù)據(jù)刷新方式。Oracle會(huì)自動(dòng)判斷是否滿足快速刷新的條件,如果滿足則進(jìn)行快速刷新,否則進(jìn)行完全刷新。
關(guān)于快速刷新:Oracle物化視圖的快速刷新機(jī)制是通過物化視圖日志完成的。Oracle通過一個(gè)物化視圖日志還可以支持多個(gè)物化視圖的快速刷新。物化視圖日志根據(jù)不同物化視圖的快速刷新的需要,可以建立為ROWID或PRIMARY KEY類型的。還可以選擇是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。
REFRESH 子句
可以包含如下部分:[refresh [fast|complete|force][on demand | commit][start with date] [next date][with {primary key|rowid}]]WITH PRIMARY KEY選項(xiàng)生成主鍵物化視圖,也就是說物化視圖是基于主表的主鍵,而不是ROWID(對應(yīng)于ROWID子句).
PRIMARY KEY是默認(rèn)選項(xiàng),為了生成PRIMARY KEY子句,應(yīng)該在主表上定義主鍵,否則應(yīng)該用基于ROWID的物化視圖.
基于ROWID物化視圖只有一個(gè)單一的主表,不能包括下面任何一項(xiàng):
(1)Distinct 或者聚合函數(shù).
(2)Group by,子查詢,連接和SET操作
當(dāng)用FAST選項(xiàng)創(chuàng)建物化視圖,必須創(chuàng)建基于主表的視圖日志.
CREATE MATERIALIZED VIEW LOG ON tableName;主鍵(PrimaryKey)物化視圖
PRIMARY KEY是默認(rèn)選項(xiàng)
在遠(yuǎn)程數(shù)據(jù)庫表acct_price_Plan上創(chuàng)建主鍵物化視圖
-- Create database link create database link PROD_DB_LINKconnect to CCusing '(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 10.xx.xx.xx)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = xgj)))';Rowid物化視圖
兩個(gè)庫 CC 和ZMC ,以zmc的emp表為操作栗子。
驗(yàn)證DBLINK的有效性
創(chuàng)建基于rowid的物化視圖
SQL> CREATE MATERIALIZED VIEW mv_emp_rowid2 REFRESH WITH ROWID3 AS SELECT * FROM emp@db_link_cc_2_zmc ;Materialized view created查詢創(chuàng)建的物化視圖
子查詢物化視圖
在遠(yuǎn)程數(shù)據(jù)庫表emp上創(chuàng)建基于emp和dept表的子查詢物化視圖
CREATE MATERIALIZED VIEW mv_empdept AS SELECT * FROM emp@db_link_cc_2_zmc e WHERE EXISTS (SELECT * FROM dept@db_link_cc_2_zmc d WHEREe.dept_no = d.dept_no)語法:
create materialized view view_name refresh [fast|complete|force] [ on [commit|demand] | start with (start_time) next (next_time) ] AS subquery;操作
創(chuàng)建物化視圖需要的權(quán)限
grant create materialized view to user_name;在源表建立物化視圖日志
create materialized view log on test_table tablespace test_space -- 日志空間 with primary key; -- 指定為主鍵類型在目標(biāo)數(shù)據(jù)庫上創(chuàng)建MATERIALIZED VIEW
START WITH子句通知數(shù)據(jù)庫完成從主表到本地表第一次復(fù)制的時(shí)間,應(yīng)該及時(shí)估計(jì)下一次運(yùn)行的時(shí)間點(diǎn), NEXT 子句說明了刷新的間隔時(shí)間.
create materialized view mv_materialized_test refresh force on demand --第一次刷新時(shí)間 start with sysdate --刷新時(shí)間間隔。每1天刷新一次,在每天10:25進(jìn)行刷新 next to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),'10:25:00'),'dd-mm-yyyy hh24:mi:ss')as select * from user_info;修改刷新時(shí)間
alter materialized view mv_materialized_test refresh force on demand start with sysdate next to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),' 23:00:00'),'dd-mm-yyyy hh24:mi:ss');或
alter materialized view mv_materialized_test refresh force on demand start with sysdate next trunc(sysdate,'dd')+1+1/24; -- 每天1點(diǎn)刷新建立索引
create index IDX_MMT_IU_TEST on mv_materialized_test(ID,UNAME) tablespace test_space;刪除物化視圖及日志
drop materialized view log on test_table; --刪除物化視圖日志: drop materialized view mv_materialized_test; --刪除物化視圖物化視圖刷新
使用dbms_mview.refresh 手工刷新
EXEC DBMS_MVIEW.REFRESH('mv_emp_rowid');--完全刷新 EXEC DBMS_MVIEW.REFRESH(LIST => 'mv_emp_rowid',METHOD => 'c'); EXEC DBMS_MVIEW.REFRESH('mv_emp_rowid','C');--快速刷新 EXEC DBMS_MVIEW.REFRESH(LIST => 'mv_emp_rowid',METHOD => 'f'); EXEC DBMS_MVIEW.REFRESH('mv_emp_rowid','F');栗子
SQL> EXEC DBMS_MVIEW.REFRESH(LIST => 'mv_emp_rowid',METHOD => 'c');PL/SQL procedure successfully completed SQL> EXEC DBMS_MVIEW.REFRESH('mv_emp_rowid','C');PL/SQL procedure successfully completed批量完全刷新
beginfor rec in (select mview_name mview_name from user_mviews)loopDBMS_MVIEW.REFRESH(rec.mview_name,'C');end loop; end;使用dbms_refresh.refresh 過程來批量刷新MV
如果我們在創(chuàng)建物化視圖的過程指定start 和next time的刷新時(shí)間,那么Oracle 會(huì)自動(dòng)創(chuàng)建刷新的job,并采用dbms_refresh.refresh 的方式。
使用這種方式刷新之前需要先make refresh group,然后才可以刷新。
Refreshmake官方語法
示例:
假設(shè)存在物化視圖MV_T1, MV_T2, MV_T3. 創(chuàng)建refresh group的語法如下:
SQL> EXEC DBMS_REFRESH.MAKE('REP_TEST', 'MV_T1,MV_T2,MV_T3', SYSDATE, 'SYSDATE+ 1')--刷新整個(gè)refresh group 組: SQL> EXEC DBMS_REFRESH.REFRESH('REP_TEST')查看物化視圖刷新狀態(tài)信息
select mview_name, refresh_method last_refresh_date, last_refresh_type,staleness from user_mviews; select * from user_mview_refresh_times;查詢物化視圖日志
物化視圖日志的名稱為MLOG$_后面跟基表的名稱,如果表名的長度超過20位,則只取前20位,當(dāng)截短后出現(xiàn)名稱重復(fù)時(shí),Oracle會(huì)自動(dòng)在物化視圖日志名稱后面加上數(shù)字作為序號。
SELECT MASTER, LOG_TABLE FROM USER_MVIEW_LOGS WHERE LOG_OWNER = UPPER(?)找到log_table 一般都是 MLOG$_ 開頭 ,然后
select * from 查詢到的log_table注意
在物化視圖的編寫過程中不可使用select * from 的形式
當(dāng)發(fā)生DML 操作時(shí),內(nèi)部的觸發(fā)器會(huì)把變化記錄到物化視圖日志里,也就是說物化視圖不支持DDL的同步,所以在物化視圖的編寫過程中不可使用select * from 的形式,因?yàn)檫@樣當(dāng)基表發(fā)生變化時(shí),物化視圖就會(huì)失效。
DDL:CREATE 、 ALTER 、DROP、 TRUNCATE、 COMMENT 、RENAME
DML:SELECT、 INSERT 、UPDATE、 DELETE、MERGE、 CALL、 EXPLAIN PLAN、LOCK TABLE
測試過程:
更新zmc.emp:
alter table emp add(sex char(5)); update emp a set a.sex='male' ; commit;刷新cc庫的物化視圖
beginfor rec in (select mview_name mview_name from user_mviews)loopDBMS_MVIEW.REFRESH(rec.mview_name,'C');end loop; end;重新查詢
INSERT-ONLY物化視圖
當(dāng)物化視圖屬于下面的某種情況,則快速刷新只支持常規(guī)DML插入和直接裝載,這種類型的物化視圖又稱為INSERT-ONLY物化視圖;
物化視圖包含MIN或MAX聚集函數(shù);
物化視圖包含SUM(expr),但是沒有包括COUNT(expr);
物化視圖沒有包含COUNT(*)。
注意:如果建立了這種物化視圖且刷新機(jī)制是ON COMMIT的,則會(huì)存在潛在的問題。當(dāng)出現(xiàn)了UPDATE或DELETE語句,除非手工完全刷新解決這個(gè)問題,否則物化視圖至此以后都不再自動(dòng)刷新,且不會(huì)報(bào)任何錯(cuò)誤。
Oracle 物化視圖 快速刷新 限制 說明
Oracle 物化視圖日志 與 快速刷新 說明
Oracle 物化視圖 詳細(xì)錯(cuò)誤描述 查看方法
總結(jié)
以上是生活随笔為你收集整理的Oracle-Materialized View解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle-知识结构漫谈
- 下一篇: Oracle-Listener log解