2012-06-22 59 views
0

我在我的應用程序中顯示符合不同標準的數據計數的情況。由於計數性能隨着數據庫的增長而下降,我們決定使用exists子句僅顯示可用性信息。Oracle - 使用多個存在來檢查記錄的可用性

下面是我的表結構

Table: DocInfo 
--------------------------------------- 
DocId  number 
DocName  varchar(250) 
DocStatus number 
SignedBy number 
ForwardedBy number 
ForwardCount number 
DocOwner number 
MgrID  number 
ProjectId number 

當前查詢該做的計數是這樣

SELECT NVL(SUM(CASE 
       WHEN (DocStatus IN (1150,1155,1170,1182,1190) AND 
         DocOwner=56366 AND 
         ForwardCount=0) 
        THEN 1 
        ELSE 0 
       END), 0) "ForReview", 
     NVL(SUM(CASE 
       WHEN (DocStatus IN (1200) And 
         MgrID = 56366 AND 
         ForwardCount = 0) 
        THEN 1 
        ELSE 0 
       END), 0) "Accepted" , 
     NVL(SUM(CASE 
       WHEN (DocStatus IN (1150,1155,1170,1182,1190) AND 
         DocOwner=56366 AND 
         MgrID = 0) 
        THEN 1 
        ELSE 0 
       END), 0) "Waiting" 
    FROM DocInfo 
    WHERE ProjectId = 313 and 
     (DocOwner = 56366 or MgrID = 56366) 

我需要計數更改爲exists條款,這樣我可以顯示是否文檔可用或不可用於每個類別。

由於此更改旨在提高性能,因此將其作爲不同的查詢運行也不可取。請幫助我,我已經耗盡了我有限的知識。

對不起,我錯過了已經嘗試過的部分。

我已經將上述查詢更改爲每個類似下面的exists子句的聯合。

SELECT 'ForReview' AS A 
    FROM DUAL 
    WHERE EXISTS (SELECT NULL 
        FROM DocInfo 
        WHERE ProjectId = 313 and 
         (DocOwner = 56366 or MgrID = 56366) and 
         (DocStatus IN (1150,1155,1170,1182,1190) AND 
         DocOwner=56366 AND 
         ForwardCount=0)) 
UNION 
    SELECT 'Accepted' AS A 
    FROM DUAL 
    WHERE EXISTS (SELECT NULL 
        FROM DocInfo 
        WHERE ProjectId = 313 and 
          (DocOwner = 56366 or MgrID = 56366) and 
          (DocStatus IN (1200) And 
          MgrID = 56366 AND 
          ForwardCount = 0)) 
UNION 
    SELECT 'Waiting' AS A 
    FROM DUAL 
    WHERE EXISTS (SELECT NULL 
        FROM DocInfo 
        WHERE ProjectId = 313 and 
          (DocOwner = 56366 or MgrID = 56366) and 
          (DocStatus IN (1150,1155,1170,1182,1190) AND 
          DocOwner=56366 AND 
          MgrID = 0)) 

我只提到了3個條件,而我的實際應用程序有8個不同的標準被添加到這個查詢中。所以當我有8個Exists子句時,它內部運行爲8個不同的查詢,實際上它需要更多時間 - 整個聯合查詢中的單個段只需要560毫秒,而所有查詢一起需要大約7秒來生成輸出。

由於我的要求只是確定可用性任何這樣的記錄,我不想瀏覽整個記錄集並計算它。

反正是有優化/重寫此查詢

謝謝

+5

爲什麼你想首先使用EXISTS?在證明它實際上解決了您的問題之前,您已經選擇了方法**。正確的問題是:(1)我有一個性能問題,描述(2)這是我嘗試的(3)我可以做些什麼來提高性能?我們也缺少很多信息,所以很難回答。你的桌子有索引嗎?數據的分佈是什麼?查詢需要多長時間?在性能方面您的目標是什麼? –

+0

對不起,我錯過了更新的問題。感謝您的信息。 – Suganth

+0

你在這張桌子上有什麼指數? DOCINFO表中有多少行A)現在,B)一個月,C)六個月? –

回答

3

「所以,當我有8個已存在的條款,它在內部運行的8個不同的 查詢,實際上需要更多的時間 - 整個聯合查詢中的單個分段只需要560毫秒,而所有查詢 需要大約7秒才能生成輸出。「

驚喜,驚喜。運行相同的查詢八個時間不會比運行該查詢一次更快。

現在確實可以使EXISTS更快,因爲它只需要找到與給定條件匹配的單個行,而不是檢索整個數據集。但是,您只是將檢索到的數據轉移到WHERE子句中,因此數據庫仍然需要執行相同的工作量。事實上,它顯然做了很多工作,因爲7s > (560ms * 8)

要正確解決您的問題,您需要了解數據庫的工作方式以及如何調整它。 Find out more

首先,定義一個調整目標。您的原始查詢需要半秒鐘才能運行:這不是閃電般的,但速度非常快。爲什麼這是個問題?你希望它運行多快?然後運行EXPLAIN PLAN。查詢使用索引?其索引使用效率如何>選擇的行數佔多大比例?

現在你還需要低估你的數據。所選數據是均勻分佈在整個表中還是存在集羣?一些項目,所有者或管理者是否有比其他項目更多的記錄?這種分配如何影響績效?

請記住,調整是一門科學,它很複雜:有關這個主題的整本書以及一些人作爲性能問題解決者做出了非常好的生活。它需要大量有關係統的信息,包括應用程序的知識以及數據庫正在執行的活動的低級信息。我們可以幫助您尋求更高性能的解決方案,但我們不能只看一個簡單的查詢,並告訴您如何重寫,以便更快地運行。

相關問題