定位导致物化视图无法快速刷新的原因
轉載自:http://yangtingkun.itpub.net/post/468/13318
物化視圖的快速刷新采用了增量的機制,在刷新時,只針對基表上發生變化的數據進行刷新。因此快速刷新是物化視圖刷新方式的首選。
但是快速刷新具有較多的約束,而且對于采用ON COMMIT模式進行快速刷新的物化視圖更是如此。對于包含聚集和包含連接的物化視圖的快速刷新機制并不相同,而且對于多層嵌套的物化視圖的快速刷新更是有額外的要求。
如此多的限制一般很難記全,當建立物化視圖失敗時,Oracle給出的錯誤信息又過于簡單,有時無法使你準確定位到問題的原因。
Oracle提供的DBMS_MVIEW.EXPLAIN_MVIEW過程可以幫助你快速定位問題的原因。下面通過一個例子來說明,如果通過這個過程來解決問題。
?
建立一個快速刷新的嵌套物化視圖:
SQL> CREATE TABLE B (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30));
表已創建。
SQL> CREATE TABLE C (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30));
表已創建。
SQL> CREATE TABLE A (ID NUMBER, BID NUMBER, CID NUMBER, NUM NUMBER,?
? 2? CONSTRAINT FK_A_B_BID FOREIGN KEY (BID) REFERENCES B(ID),?
? 3? CONSTRAINT FK_A_C_BID FOREIGN KEY (CID) REFERENCES C(ID));
表已創建。
SQL> INSERT INTO B SELECT ROWNUM, 'B'||ROWNUM FROM USER_TABLES WHERE ROWNUM <= 6;
已創建6行。
SQL> INSERT INTO C SELECT ROWNUM, 'C'||ROWNUM FROM USER_TABLES WHERE ROWNUM <= 4;
已創建4行。
SQL> INSERT INTO A SELECT ROWNUM, TRUNC((ROWNUM - 1)/2) + 1, TRUNC((ROWNUM - 1)/3) + 1, ROWNUM?
? 2? FROM USER_TABLES
? 3? WHERE ROWNUM <= 12;
已創建12行。
SQL> COMMIT;
提交完成。
上面建立好基表,下面建立第一層物化視圖。
SQL> CREATE MATERIALIZED VIEW LOG ON A WITH ROWID;
實體化視圖日志已創建。
SQL> CREATE MATERIALIZED VIEW LOG ON B WITH ROWID;
實體化視圖日志已創建。
SQL> CREATE MATERIALIZED VIEW LOG ON C WITH ROWID;
實體化視圖日志已創建。
SQL> CREATE MATERIALIZED VIEW MV_ABC REFRESH FAST ON COMMIT ENABLE QUERY REWRITE AS
? 2? SELECT C.ID CID, C.NAME CNAME, B.ID BID, B.NAME BNAME, A.NUM,?
? 3? A.ROWID AROWID, B.ROWID BROWID, C.ROWID CROWID?
? 4? FROM A, B, C WHERE A.BID = B.ID AND A.CID = C.ID;
實體化視圖已創建。
第一次物化視圖已經建立成功,下面建立嵌套物化視圖:
SQL> CREATE MATERIALIZED VIEW LOG ON MV_ABC WITH ROWID (BNAME, CNAME, NUM) INCLUDING NEW VALUES;
實體化視圖日志已創建。
SQL> CREATE MATERIALIZED VIEW MV_MV_ABC REFRESH FAST ON COMMIT ENABLE QUERY REWRITE AS
? 2? SELECT CNAME, BNAME, COUNT(*) COUNT, SUM(NUM) SUM_NUM FROM MV_ABC
? 3? GROUP BY CNAME, BNAME;
SELECT CNAME, BNAME, COUNT(*) COUNT, SUM(NUM) SUM_NUM FROM MV_ABC
?????????????????????????????????????????????????????????? *
ERROR 位于第 2 行:
ORA-12053: 這不是一個有效的嵌套實體化視圖
錯誤出現了,不過錯誤的描述包含的信息量并不大。我們看看Oracle的文檔上是如何描述這個錯誤的。
ORA-12053 this is not a valid nested materialized view
Cause:?The list of objects in the FROM clause of the definition of this materialized view had some dependencies upon each other.
Action:?Refer to the documentation to see which types of nesting are valid.
文檔上的描述也是十分籠統的,并沒有指出具體問題所在。
接下來,我們通過使用DBMS_MVIEW.EXPLAIN_MVIEW過程來定位錯誤。
使用EXPLAIN_MVIEW過程首先要建立MV_CAPABILITIES_TABLE表,建表的腳步是$ORACLE_HOME/rdbms/admin/utlxmv.sql。(EXPLAIN_MVIEW過程是兩個過程的重載,一個輸出到MV_CAPABILITIES_TABLE表,另一個以PL/SQL的VARRAY格式輸出,為了簡單起見,我們建立MV_CAPABILITIES_TABLE表)。
SQL> @?rdbmsadminutlxmv.sql
表已創建。
下面簡單研究一下EXPLAIN_MVIEW過程。
DBMS_MVIEW.EXPLAIN_MVIEW(mv IN VARCHAR2, Statement_id IN VARCHAR2:= NULL);
該過程可以輸入已經存在的物化視圖名稱(或USER_NAME.MV_NAME),也可輸入建立物化視圖的查詢語句。另外一個參數STATEMENT_ID輸入一個語句ID,為了標識出表中對應的記錄。
SQL> BEGIN
? 2? DBMS_MVIEW.EXPLAIN_MVIEW('SELECT CNAME, BNAME, COUNT(*) COUNT, SUM(NUM) SUM_NUM FROM MV_ABC?
? 3? GROUP BY CNAME, BNAME', 'MV_MV_ABC');
? 4? END;
? 5? /
PL/SQL 過程已成功完成。
SQL> SELECT CAPABILITY_NAME, RELATED_TEXT, MSGTXT FROM MV_CAPABILITIES_TABLE
? 2? WHERE STATEMENT_ID = 'MV_MV_ABC' AND POSSIBLE = 'N' AND CAPABILITY_NAME NOT LIKE '%PCT%';
CAPABILITY_NAME??????????????? RELATED_TEXT??? MSGTXT
------------------------------ --------------- --------------------------------------------------
REFRESH_FAST_AFTER_ONETAB_DML? SUM_NUM???????? 使用 SUM(expr) 時, 未提供 COUNT(expr)
REFRESH_FAST_AFTER_ANY_DML???? YANGTK.MV_ABC?? mv 日志沒有序列號
REFRESH_FAST_AFTER_ANY_DML???????????????????? 查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因
根據上面的信息,已經可以確定問題的原因了,對于聚集物化視圖,使用了SUM(COLUMN),但是沒有包括COUNT(COLUMN)。
修改物化視圖,重新建立:
SQL> CREATE MATERIALIZED VIEW MV_MV_ABC REFRESH FAST ON COMMIT ENABLE QUERY REWRITE AS
? 2? SELECT CNAME, BNAME, COUNT(*) COUNT, COUNT(NUM) NUM_COUNT, SUM(NUM) SUM_NUM FROM MV_ABC
? 3? GROUP BY CNAME, BNAME;
實體化視圖已創建。
總結
以上是生活随笔為你收集整理的定位导致物化视图无法快速刷新的原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在shell脚本中调用sqlplus
- 下一篇: 段的创建表user_segments