2011-11-21 93 views
5

我在Oracle中有一個包含LEFT JOIN的物化視圖,需要很長時間才能更新。當我更新底層表時,需要運行63914.765秒(是的,差不多17小時)。Oracle - 快速刷新帶有左連接的物化視圖更新非常慢

我在同一張表上使用了LEFT JOIN,因爲我想將數據從行轉移到列。在此Oracle版本中,pivot命令不可用,並且在FAST REFRESH物化視圖上不允許使用GROUP BY + CASE。

物化視圖日誌看起來是這樣的:

CREATE MATERIALIZED VIEW LOG ON Programmes_Titles 
WITH PRIMARY KEY, rowid 
INCLUDING NEW Values; 

物化視圖本身看起來像這樣(包含70萬行,在Programmes_Titles表包含900000行):

CREATE MATERIALIZED VIEW Mv_Web_Programmes 
REFRESH FAST ON COMMIT 
AS 

SELECT 
    t1.ProgrammeId,   
    t1.Title as MainTitle, 
    t2.Title as SecondaryTitle, 
    --Primary key 
    t1.Title_Id as t1_titleId, 
    t2.Title_Id as t2_titleId, 

    t1.rowid as t1_rowid, 
    t2.rowid as t2_rowid 
FROM 
    Programmes_Titles t1, 
    Programmes_Titles t2 
WHERE 
    t1.Titles_Group_Type = 'mainTitle' 
    AND t1.Programme_Id = t2.Programme_Id(+) AND t2.Titles_Group_Type(+) = 'secondaryTitle' 

UPDATE語句我用的是這樣的:

UPDATE Programmes_Titles 
SET Title = 'New title' 
WHERE rowid = 'AAAL4cAAEAAAftTABB' 

這個UPDATE語句ta kes 17個小時。 使用INNER JOIN(刪除(+))時,需要幾毫秒。

我也嘗試在Mv_Web_Programmes物化視圖中添加INDEXES,但這似乎也沒有幫助。 (它仍然運行超過一分鐘,這是緩慢的方式,我不等待17小時後,每次更改,所以它可能會改善更新)

所以我的問題是:爲什麼需要這麼長時間更新底層表?我該如何改進?

回答

3

我已經設法在10.2.0.3實例上重現您的問題。自連接和外連接似乎是主要問題(儘管MV中每一列的索引都會在一分鐘內完成更新)。

起初我還以爲你可以使用聚合MV:

SQL> CREATE MATERIALIZED VIEW LOG ON Programmes_Titles 
    2 WITH PRIMARY KEY, ROWID (programmeId, Titles_Group_Type, title) 
    3 INCLUDING NEW Values; 

Materialized view log created 

SQL> CREATE MATERIALIZED VIEW Mv_Web_Programmes 
    2 REFRESH FAST ON COMMIT 
    3 AS 
    4 SELECT ProgrammeId, 
    5   MAX(decode(t1.Titles_Group_Type, 'mainTitle', t1.Title)) MainTl, 
    6   MAX(decode(t1.Titles_Group_Type, 'secondaryTitle', t1.Title)) SecTl 
    7 FROM Programmes_Titles t1 
    8 GROUP BY ProgrammeId; 

Materialized view created 

不幸的是,因爲你已經注意到,隨着萬兆a MV that contains MIN or MAX can only be fast-refreshed on commit after insert的(所謂的唯一刀片式MV)。上述解決方案不適用於更新/刪除(MV將不得不手動刷新)。

您可以跟蹤會話並打開跟蹤文件以查看執行了哪些SQL查詢,以便您可以查找是否可以通過索引對其進行優化。

+0

謝謝,建議的解決方案工作完美。還有一個問題。在我的示例查詢中,我只在JOIN中使用單個條件,但我真正的查詢使用了兩個。我仍然可以使用DECODE功能(這對我來說是新的,還是應該使用CASE?) – Tejo

+0

對不起,我有點快。 Programme_Titles表在一秒鐘內獲得新值,但Mv_Web_Programmes不更新,舊值仍然存在。 任何想法? – Tejo

+0

只要您在CASE語句中使用的每一列都在MV日誌中,您就應該可以使用CASE而不是DECODE。 –

1

我們也面臨這個問題最近在Oracle 11.2.0.3

在我們的情況下,這是不可避免的要刪除一個「OUTER JOIN」由於功能的影響。

經調查發現,Oracle正在用MV刷新DML添加令人討厭的HASH_SH(哈希半連接)提示。

毫無效果包括以下blog- http://www.adellera.it/blog/2010/03/11/fast-refresh-of-join-only-mvs-_mv_refresh_use_stats-and-locking-log-stats/#comment-2975

在最後提到的事情,一個隱藏的提示工作...

(儘管在一般情況下,應該通過在應用程序,如果可能,改變避免)

Oracle Doc ID 1949537.1建議將隱藏的_mv_refresh_use_hash_sj參數設置爲FALSE應該防止使用該提示。

alter session set "_mv_refresh_use_hash_sj"=FALSE; 

使用HASH_SJ提示停止了CBO。

張貼在這裏是爲了他人的利益。