2016-08-17 2657 views
1

我在爲我們的聚合創建物化視圖時遇到問題。如果源表上出現DML,則實例化視圖應自動刷新並顯示更新後的結果。這個想法是存儲聚合結果,並直接獲取數字而不是查詢,我基本上想看看這是否符合我們的目標。我們的桌子每天將有多達300萬個插頁。ORA-12054:無法爲物化視圖設置ON COMMIT刷新屬性

按照鏈接Example 8-3 Example 3: Creating a Materialized View我所做的:

CREATE MATERIALIZED VIEW LOG ON table WITH SEQUENCE, ROWID 
(SUBJECTID) 
INCLUDING NEW VALUES; 

CREATE MATERIALIZED VIEW ih_data_aggregated_view 
PARALLEL 
BUILD IMMEDIATE 
REFRESH FAST ON COMMIT 
AS 
SELECT SUBJECTID ,count(*)as totalcount ,avg(price)as avgprice,sum(price) as totalprice 
FROM table 
WHERE SUBJECTID='xxxxx' GROUP by SUBJECTID; 

不過這樣會:

java.sql.SQLException: SQLException: ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view

+3

你看過[限制](https://docs.oracle.com/cd/E11882_01/server.112/e25554/basicmv.htm#i1007028)嗎? –

+2

「對於每個集合(如AVG(expr)),必須存在相應的COUNT(expr)。」。 您應該嘗試更改'計數(*)'爲'計數(價格)' – vercelli

回答

3

文檔包括general restrictions on materialised viewmaterialised view with aggregates

,同時通過這些名單的工作是有益的,你可以看到現有的或潛在的物化視圖是否可被從the dbms_mview.explain_mview procedure檢查結果快速刷新:

set serveroutput on 
declare 
    msg_array SYS.ExplainMVArrayType; 
begin 
    dbms_mview.explain_mview (q'[ 
SELECT SUBJECTID ,count(*)as totalcount ,avg(price)as avgprice,sum(price) as totalprice 
FROM your_table 
WHERE SUBJECTID='xxxxx' 
GROUP by SUBJECTID 
]', 
    msg_array); 
    for i in msg_array.first..msg_array.last loop 
    dbms_output.put_line(rpad(msg_array(i).capability_name, 30) 
     ||' '|| msg_array(i).possible 
     ||' '|| msg_array(i).msgtxt); 
    end loop; 
end; 
/

... 
REFRESH_FAST     F 
... 
REFRESH_FAST_AFTER_INSERT  F agg(expr) requires correspondng COUNT(expr) function 
REFRESH_FAST_AFTER_ONETAB_DML F SUM(expr) without COUNT(expr) 
REFRESH_FAST_AFTER_ONETAB_DML F see the reason why REFRESH_FAST_AFTER_INSERT is disabled 
REFRESH_FAST_AFTER_ANY_DML  F see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled 
REFRESH_FAST_PCT    F PCT is not possible on any of the detail tables in the materialized view 
... 

正如@vercelli提及,並作爲REFRESH_FAST_AFTER_INSERT消息提示,您需要將count(*)更改爲count(price)。但那不是整個故事;如果你只是改變你會看到:

REFRESH_FAST     F 
... 
REFRESH_FAST_AFTER_INSERT  F mv log does not have all necessary columns 
REFRESH_FAST_AFTER_ONETAB_DML F see the reason why REFRESH_FAST_AFTER_INSERT is disabled 
REFRESH_FAST_AFTER_ONETAB_DML F COUNT(*) is not present in the select list 
REFRESH_FAST_AFTER_ANY_DML  F see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled 

你的物化視圖日誌必須包括列您彙總:

CREATE MATERIALIZED VIEW LOG ON your_table WITH SEQUENCE, ROWID 
(SUBJECTID,PRICE) 
INCLUDING NEW VALUES; 

Materialized view LOG created. 

CREATE MATERIALIZED VIEW ih_data_aggregated_view 
PARALLEL 
BUILD IMMEDIATE 
REFRESH FAST ON COMMIT 
AS 
SELECT SUBJECTID ,count(price)as totalcount ,avg(price)as avgprice,sum(price) as totalprice 
FROM your_table 
WHERE SUBJECTID='xxxxx' 
GROUP by SUBJECTID; 

Materialized view IH_DATA_AGGREGATED_VIEW created. 

缺少count(*)仍報告,但由於這是針對單個表它不能防止快速刷新。值得注意的是,如果您的price列可以爲空,則count(price)count(*)可能會給出不同的結果;如果是這種情況,您可能希望將這兩個數字作爲MV中的列。

+0

嗨亞歷克斯謝謝你的詳細答案。我仍然面臨同樣的問題。 REFRESH_FAST_AFTER_INSERT功能說明它更好:mv日誌沒有所有必要的列。當我執行你的過程時,它顯示我REFRESH_FAST_AFTER_INSERT F mv日誌沒有所有必需的列。我使用你提到的查詢創建了視圖.Oracle Database 12c企業版發佈12.1.0.1.0 - 64位生產 – MrWayne

+0

@MWWayne - 您是否重新創建MV日誌以包含價格列? –

+0

是的,我did.Exact命令我遵循創建MV創建材料化視圖登錄PR_DATA_IH_FACT_MILLION與序列,ROWID(SUBJECTID,價格)包括新的價值; – MrWayne