介紹
物化視圖是一種特殊的物理表,“物化”(Materialized)視圖是相對普通視圖而言的。普通視圖是虛擬表,應用的局限性大,任何對視圖的查詢,Oracle都實際上轉換為視圖SQL語句的查詢。這樣對整體查詢性能的提高,並沒有實質上的好處。
1、物化視圖的類型:ON DEMAND、ON COMMIT
二者的區別在於刷新方法的不同,ON DEMAND顧名思義,僅在該物化視圖“需要”被刷新了,才進行刷新(REFRESH),即更新物化視圖,以保證和基表數據的一致性;而ON COMMIT是說,一旦基表有了COMMIT,即事務提交,則立刻刷新,立刻更新物化視圖,使得數據和基表一致。
2、ON DEMAND物化視圖
物化視圖的創建本身是很復雜和需要優化參數設置的,特別是針對大型生產數據庫系統而言。但Oracle允許以這種最簡單的,類似於普通視圖的方式來做,所以不可避免的會涉及到默認值問題。也就是說Oracle給物化視圖的重要定義參數的默認值處理是我們需要特別注意的。
物化視圖的特點:
(1) 物化視圖在某種意義上說就是一個物理表(而且不僅僅是一個物理表),這通過其可以被user_tables查詢出來,而得到佐證;
(2) 物化視圖也是一種段(segment),所以其有自己的物理存儲屬性;
(3) 物化視圖會占用數據庫磁盤空間,這點從user_segment的查詢結果,可以得到佐證;
創建語句:create materialized view mv_name as select * from table_name
默認情況下,如果沒指定刷新方法和刷新模式,則Oracle默認為FORCE和DEMAND。
3、物化視圖的數據怎么隨着基表而更新?
Oracle提供了兩種方式,手工刷新和自動刷新,默認為手工刷新。也就是說,通過我們手工的執行某個Oracle提供的系統級存儲過程或包,來保證物化視圖與基表數據一致性。這是最基本的刷新辦法了。自動刷新,其實也就是Oracle會建立一個job,通過這個job來調用相同的存儲過程或包,加以實現。
4、ON DEMAND物化視圖的特性及其和ON COMMIT物化視圖的區別
前者不刷新(手工或自動)就不更新物化視圖,而后者不刷新也會更新物化視圖,——只要基表發生了COMMIT。
創建定時刷新的物化視圖:
create materialized view mv_name refresh force on demand start with sysdate next sysdate+1 (指定物化視圖每天刷新一次)
上述創建的物化視圖每天刷新,但是沒有指定刷新時間,如果要指定刷新時間(比如每天晚上10:00定時刷新一次):
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')
5、ON COMMIT物化視圖
ON COMMIT物化視圖的創建,和上面創建ON DEMAND的物化視圖區別不大。因為ON DEMAND是默認的,所以ON COMMIT物化視圖,需要再增加個參數即可。
需要注意的是,無法在定義時僅指定ON COMMIT,還得附帶個參數才行。
創建ON COMMIT物化視圖:
create materialized view mv_name refresh force on commit as select * from table_name
備注:實際創建過程中,基表需要有主鍵約束,否則會報錯(ORA-12014)
6、物化視圖的刷新
刷新(Refresh):指當基表發生了DML操作后,物化視圖何時采用哪種方式和基表進行同步。刷新的模式有兩種:ON DEMAND和ON COMMIT。(如上所述)
刷新的方法有四種:FAST、COMPLETE、FORCE和NEVER。
FAST刷新采用增量刷新,只刷新自上次刷新以后進行的修改。COMPLETE刷新對整個物化視圖進行完全的刷新。如果選擇FORCE方式,則Oracle在刷新時會去判斷是否可以進行快速刷新,如果可以則采用FAST方式,否則采用COMPLETE的方式。NEVER指物化視圖不進行任何刷新。
對於已經創建好的物化視圖,可以修改其刷新方式,比如把物化視圖mv_name的刷新方式修改為每天晚上10點刷新一次:
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')
7、物化視圖具有表一樣的特征,所以可以像對表一樣,我們可以為它創建索引,創建方法和對表一樣。
8、物化視圖的刪除:
雖然物化視圖是和表一起管理的,但是在經常使用的PLSQL工具中,並不能用刪除表的方式來刪除(在表上右鍵選擇‘drop’並不能刪除物化視圖),可以使用語句來實現:
drop materialized view mv_name
其他參考
普通視圖和物化視圖的區別
普通視圖和物化視圖根本就不是一個東西,說區別都是硬拼到一起的,首先明白基本概念,普通視圖是不存儲任何數據的,他只有定義,在查詢中是轉換為對應的定義SQL去查詢,而物化視圖是將數據轉換為一個表,實際存儲着數據,這樣查詢數據,就不用關聯一大堆表,如果表很大的話,會在臨時表空間內做大量的操作。
普通視圖的三個特征:
1、是簡化設計,清晰編碼的東西,他並不是提高性能的,他的存在只會降低性能(如一個視圖7個表關聯,另一個視圖8個表,程序員不知道,覺得很方便,把兩個視圖關聯再做一個視圖,那就慘了),他的存在未了在設計上的方便性
2、其次,是安全,在授權給其他用戶或者查看角度,多個表關聯只允許查看,不允許修改,單表也可以同WITH READ ONLY來控制,當然有些項目基於視圖做面向對象的開發,即在視圖上去做INSTAND OF觸發器,就我個人而言是不站同的,雖然開發上方便,但是未必是好事。
3、從不同的角度看不同的維度,視圖可以划分維度和權限,並使多個維度的綜合,也就是你要什么就可以從不同的角度看,而表是一個實體的而已,一般維度較少(如:人員表和身份表關聯,從人員表可以查看人員的維度統計,從身份看,可以看不同種類的身份有那些人或者多少人),其次另一個如系統視圖USER_TABLE、TAB、USER_OBJECTS這些視圖,不同的用戶下看到的肯定是不一樣的,看的是自己的東西。
物化視圖呢,用於OLAP系統中,當然部分OLTP系統的小部分功能未了提高性能會借鑒一點點,因為表關聯的開銷很大,所以在開發中很多人就像把這個代價交給定期轉存來完成,ORACLE當然也提供了這個功能,就是將視圖(或者一個大SQL)的信息轉換為物理數據存儲,然后提供不同的策略:定時刷還是及時刷、增量刷還是全局刷等等可以根據實際情況進行選擇,總之你差的是表,不是視圖。
關於在刷新和索引上的區別
他們兩個沒有聯系吧,刷新我不清楚你是否指的是物化視圖的刷新,因為刷新的概念很泛,你說到這里我就理解為物化視圖的刷新了,上面也已經說了,這是一種策略和方法,其實它是通過對視圖關聯表上創建相應的LOG,根據日志信息的SQL同步到物化視圖中的,一般來說:定時的一般是全局刷,及時的一般是局部刷。
而索引這個說起來就多了,可以說索引專門是一門課程,大概點來說,索引一般有普通索引、位圖索引、唯一性索引(還有全文索引啥的,一般不用),其實仔細研究會發現無論是那一種索引都是B+樹為基礎,並起存放方式和表一樣,是以段為單位,只是內部有樹關系而已。
1、普通索引是根據B+樹找到第一個(索引時有序的),然后以當前為基准,向后順序找到不符合條件的健值為止。
2、位圖是在葉子節點上根據位圖種類對葉子節點的值進行01編碼存放(如該字段有1、2、3三種值,就會在葉子節點上有三個位圖,每個位圖根據健值和ROWID順序存放是否為1、是否為2、是否為3,所以在RBO下統計很快,CBO下一般會認為是普通索引)。
3、也是按照B+樹找,只是找到就不再做任何操作,因為是唯一的。
因為B+查找是一個類似表的查詢,而且獲取到ROWID后還是要回表查詢的,所以這個過程的開銷要和全表掃描計算那個結果更加快,ORACLE才會選擇是走索引還是走全表掃描,當然對於CBO和RBO選擇的方式不一樣,具體又是很多,CBO要依賴於表的統計信息,RBO是依賴於嘗試。
有用過ORCLE 物化視圖的朋友,請幫個忙,我想每天刷新兩次,比如中午十二點,晚上七點,不知道怎么寫,急用!
你這個需要,可以這樣實現
建一個表,再寫個存儲過程
再用個SCHEDULE JOB來實現
用普通JOB,或者物化視圖,對於時間間隔都需要有規律
或者寫個儲存過程來手工刷新物化視圖,然后用SCHEDULE JOB來實現每天12點,19點刷新
對於oracle10g簡單方法:
1. 先建立一個物化視圖,不用指明刷新參數,只要create materialized view,如
CREATE MATERIALIZED VIEW mv_emp
AS SELECT * FROM scott.emp;
2. 建立一個用來刷新物化視圖的存儲過程,如
CREATE OR REPLACE PROCEDURE auto_refresh_mview_job_proc
AS
BEGIN
dbms_mview.REFRESH('mv_emp');
END;
/
3. 用ORACLE 10g的scheduler每天12:00和19:00定期刷新物化視圖
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'auot_refresh_mview_job',
job_type => 'STORED_PROCEDURE',
job_action => 'scott.auto_refresh_mview_job_proc',
start_date => SYSDATE,
repeat_interval => 'FREQ=DAILY; BYHOUR=12,19',
enabled => TRUE,
comments => 'Refresh materialized view mv_emp'
);
END;
/
4. 刪除scheduler對象的方法
BEGIN
DBMS_SCHEDULER.DROP_JOB(
job_name => 'auot_refresh_mview_job'
);
END;
/
dbms_mview.REFRESH('mv_emp'); 這個是我想要的,謝謝了,還有,如果我之前用alter materialized view '|| a.table_name||' refresh complete start with sysdate next sysdate+100/(24*60*60)'||';' 建的刷新,怎么取消啊。
把刷新物化視圖的JOB 刪除了就可以了,下面是查詢物化視圖及對應的jobno的語句:
SELECT job, what from user_jobs;
找到jobno后,用dbms_Job.remove就可以刪除job了
exec dbms_job.remove(:jobno);
3. 用ORACLE 10g的scheduler每天12:00和19:00定期刷新物化視圖
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'auot_refresh_mview_job',
job_type => 'STORED_PROCEDURE',
job_action => 'scott.auto_refresh_mview_job_proc',
start_date => SYSDATE,
repeat_interval => 'FREQ=DAILY; BYHOUR=12,19',
enabled => TRUE,
comments => 'Refresh materialized view mv_emp'
);
上面這種方式我不怎么明白。
物化視圖的定時刷新其實是用Oracle的任務實現的,就是按照刷新的時間間隔定期的執行DBMS_MVIEW.REFRESH('mv_emp')的.由於Oracle10g增加了功能更為強大的scheduler功能,可以更加靈活的定義執行任務的時間,因此這里我給出的方法就是用10g的SCHEDULER,用scheduler要用到Oracle的內部包DBMS_SCHEDULER,其中DBMS_SCHEDULER.CREATE_JOB就是來創建一個實時執行的任務,下面是一個例子
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'auto_refresh_mview_job',
job_type => 'STORED_PROCEDURE',
job_action => 'scott.auto_refresh_mview_job_proc',
start_date => SYSDATE,
repeat_interval => 'FREQ=DAILY; BYHOUR=12,19',
enabled => TRUE,
comments => 'Refresh materialized view mv_emp'
);
job_name對應的參數是任務名,這個任務的名字就是'auto_refresh_mview_job'
job_type是任務的類型,這里是存儲過程類型
job_action是任務的名稱,這里就是存儲過程'scott.auto_refresh_mview_job_proc',存儲過程的功能就是執行dbms_mviw.refresh('mv_emp')
start_date是開始執行的時間,這里是從任務創建時就開始執行
repeat_interval是執行的時間間隔,FREQ表示執行頻率,DAILY表示每天執行,BYHOUR定義了具體的執行時間為每天的12時和19時
enabled表示任務為啟用狀態,如果不加這個參數,為缺省的不啟用
comments為任務的一個說明,這里面的內容可以根據實際情況自行填寫。
定義了上面的任務后,可以從字典表dba_scheduler_jobs查詢出這個任務來。
手動刷新
BEGIN DBMS_MVIEW.REFRESH ( list => 'viewname', Method =>'C', refresh_after_errors => True); END;
參數:
我們常常利用物化視圖來同步數據,或者遷移數據。在dbms_mview中的刷新過程,可以使用並行刷新的特性,可以有效的減少完全刷新的時間,下面是一個過程示例:
create materialized view log on test; --創建物化視圖日志
create table mv_test as select * from test@lnk_testdb where 1=2; --創建與源表相同的表結構
create materialized view mv_test on prebuilt table refresh fast as
select * from test@lnk_testdb; --創建物化視圖
我們來看一下,我們常用的刷新過程參數含義:
PROCEDURE REFRESH
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
TAB TABLE OF VARCHAR2(227) IN/OUT
METHOD VARCHAR2 IN DEFAULT
ROLLBACK_SEG VARCHAR2 IN DEFAULT
PUSH_DEFERRED_RPC BOOLEAN IN DEFAULT
REFRESH_AFTER_ERRORS BOOLEAN IN DEFAULT
PURGE_OPTION BINARY_INTEGER IN DEFAULT
PARALLELISM BINARY_INTEGER IN DEFAULT --這里是並行控制參數
HEAP_SIZE BINARY_INTEGER IN DEFAULT
ATOMIC_REFRESH BOOLEAN IN DEFAULT
NESTED BOOLEAN IN DEFAULT
比如說我們要全刷新一張mv_test物化視圖:
begin
dbms_mview.refresh(TAB=>'MV_TEST',
METHOD=>'COMPLETE',
PARALLELISM=>8);
end;
/
dbms_mview.refresh('表名', 'F') --快速刷新,也就是增量刷新
dbms_mview.refresh('表名', 'C')--完全刷新
這個有什么問題
你只看前兩個就行了,list是你要刷新的表名列表,method 就是你要執行刷新的方式
增量刷新就不需要使用什么並行了,通常情況下,是沒有那個必要的。
begin
dbms_mview.refresh(TAB=>'MV_TEST',
METHOD=>'FAST',
PARALLELISM=>1);
end;
/
謝謝下面網友的提醒,對此文糾正一些錯誤,如果只是在刷新的時候,指定此parallelism並行參數,實際上並不能啟用起並行,下面是文檔中原文描述:
At the outset, it appears that the PARALLELISM parameter will invoke a parallel refresh of the materialized view. However, it doesn’t. The dynamic performance views V$PX_PROCESS and V$PX_SESSION provide information on the parallel execution processes and the sessions using parallel execution respectively. When the above refresh process is running, if we query these views, we will see that there are no parallel execution processes in use.
如果想在刷新的時候,啟用並行,可以采用如下的三種辦法:
1.修改master表的並行度屬性
2.創建物化視圖日志定義並行度屬性
3.創建物化視圖時,使用hint
有時間再對這個測試一下,后面補充的信息的參考文檔為:
http://www.doug.org/newsletter/march/MV_Refresh_Parallel.pdf
