2012-06-06 101 views
0

我有兩個表A和B,其中A中的記錄被映射到B中的多個記錄。有查詢顯示錶A的記錄以及所有映射的記錄在一個單一的線表B中,如:Oracle 1:n高效查詢

TABLE A 
-------- 
ID Name Tag ...... 
1 X 213 
2 Y 222 

TABLE B 
-------- 
ID ACCESS_AREA 
1  101 
1  104 
1  105 
2  101 
2  103 

該查詢是這樣的:

SELECT ID, 
     Name, 
     Tag ,....., 
     (SELECT WM_CONCAT(ACCESS_AREA) 
      FROM B 
      WHERE ID = A.ID) Access_areas 
    FROM A 

雖然上述工程中,查詢的性能是非常低的,因爲在這兩個記錄數桌子非常大。任何對access_areas進行過濾或排序都會導致性能進一步下降。

我們考慮過使用物化視圖來事先計算這些值,以便它成爲一個簡單的聯接,但mv不允許使用聚合函數快速刷新此類查詢的提交。

另一種方法是向表A添加一列,該列包含B的計算值,並在表B中使用觸發器更新新列(如果發生任何更改)。但是這也不可行,因爲您無法查詢觸發器所在的同一個表。

作爲最後的手段,我們決定實現第二個選項並通過應用程序代碼更新列,這非常乏味。

任何想法?

回答

1

您沒有顯示查詢的EXPLAIN計劃,也沒有顯示錶的索引。但更重要的是,您沒有告訴我們您使用這些數據所做的工作 - 爲什麼您一次需要訪問大量數據?你爲什麼需要對結果進行denosmalise?

您可以創建一個視圖,其中包含自從創建快照以來更新的物化視圖和原始數據(並可能刪除不再有效的更新條目),但沒有關於數據如何使用的一些想法/是否它是不斷更新而不是僅僅添加到它是不是真的可以提供具體建議。

+0

對不起,無論我提到的是一個類似於我面臨的場景的例子。實際上我們有兩個更類似的計算列。另外,不幸的是,我在設計規範中沒有發言權。 – Rnet

+0

有一個前端界面,它列出了單個頁面中第一個表格及其相關表格的所有記錄,因此查詢 – Rnet

+0

「頁面」是指HTML嗎?然後不用擔心 - 與通過HTTP傳遞此性能問題相比,查詢性能問題**沒有任何**,並嘗試使用HTML進行呈現。現在開始磨合你的簡歷 – symcbean

0

1.將WM_CONCAT替換爲LISTAGGCOLLECT

由於SQL和PL/SQL之間頻繁的上下文切換,大型字符串聚合可能非常昂貴。 WM_CONCATSTRAGG,都非常受歡迎,但它們都非常低效。如果您使用的是11gR2,請始終使用LISTAGG。如果您尚未使用11gR2,請使用COLLECT方法。 This page解釋了不同的方法並進行了一些性能比較。

2.物化視圖。

我知道你說你已經嘗試過了,而且我沒有很多物化視圖的經驗,但我認爲他們應該在這種情況下工作。 rowid物化視圖將不起作用,但primary key materialized view應該。

(除非有其他一些具體的原因阻止它,在這種情況下,我們可能需要的所有細節troublesheet問題:桌子的完整的查詢和DDL,物化視圖和物化視圖日誌。)

3.解釋計劃。

正如symcbean所述,這可能是一個計劃問題。如果只使用少量的行,是否使用了索引?但除了解釋計劃之外,我們需要知道您對此查詢的期望。如果查詢需要一秒鐘,但返回200KB的數據,那麼您的網絡或瀏覽器可能是真正的瓶頸。


我不確定#2或#3是否會有幫助,但您應該始終執行#1。我認爲WM_CONCATSTRAGG是bug - 當有更好的選擇時,沒有什麼好的理由使用它們。