2012-01-24 57 views
3

我有以下查詢:性能查詢很不好

SELECT so1b.hasattachments, 
     so1b.sorefitem, 
     so1b.sonumber, 
     so1b.custponumber, 
     so1b.sodate, 
     so1b.ostatus, 
     so1b.osubstatus, 
     so1b.urefitem, 
     so1b.username, 
     so1b.summary, 
     so1b.purefitem 
FROM (SELECT DECODE (COUNT (ATT.SOREFITEM), 0, 0, 1) hasattachments, 
      so1.SOREFITEM, 
      SONUMBER, 
      CUSTPONUMBER, 
      SODATE, 
      so1.OSTATUS, 
      so1.OSUBSTATUS, 
      so1.urefitem AS urefitem, 
      so1.username AS username , 
      ''   AS summary , 
      so1.PUREFITEM 
     FROM ECOrders.SALESORDERS so1, 
      ECORDERS.ATTACHMENTS att, 
      ecusers.ownership o 
     WHERE att.SOREFITEM (+) =so1.SOREFITEM 
     AND so1.UREFITEM  = o.urefitem 
     AND o.uownerref   = ? 
     AND so1.sorefitem  IN 
      (SELECT ot.sorefitem 
      FROM ECOrders.ORDERITEMS ot, 
        ECUSERS.USERINFO USI 
      WHERE ot.sorefitem=so1.sorefitem 
       AND OT.OSELLERID = USI.UREFITEM (+) 
       AND UPPER(USI.USERNAME) LIKE UPPER('%Dell Computer%') ESCAPE '~' 
      ) 
     GROUP BY SO1.SOREFITEM, 
      SONUMBER, 
      CUSTPONUMBER, 
      SODATE, 
      so1.OSTATUS, 
      so1.OSUBSTATUS, 
      so1.UREFITEM, 
      so1.USERNAME, 
      so1.PUREFITEM 
     ORDER BY SOREFITEM DESC /* sort is possible on all columns */ 
    ) so1b 
WHERE rownum BETWEEN 1 AND 10 

此查詢執行時的數據是大非常糟糕。執行計劃如下:

ID PA_ID Execution Plan                  COST CARD BYTES 
0  SELECT STATEMENT Optimizer=CHOOSE              2906 10  9480 
1 0 -COUNT (STOPKEY)    
2 1 --FILTER    
3 2 ---VIEW                     2906 381  361188 
4 3 ----SORT (GROUP BY)                  2906 381  32766 
5 4 -----FILTER   
6 5 ------NESTED LOOPS (OUTER)                18  2888 248368 
7 6 -------NESTED LOOPS                  17  2888 231040 
8 7 --------TABLE ACCESS (BY INDEX ROWID) of 'ECUSERS.OWNERSHIP' (TABLE)     1  24  240 
9 8 ---------INDEX (RANGE SCAN) of 'ECUSERS.OWNERSHIP_UOWNERREF' (INDEX)     1  24 
10 7 --------TABLE ACCESS (BY INDEX ROWID) of 'ECORDERS.SALESORDERS' (TABLE)     1  121  8470 
11 10 ---------INDEX (RANGE SCAN) of 'ECORDERS.SO_UREFITEM_OSTATUS_OSUB' (INDEX)    1  76 
12 6 -------INDEX (RANGE SCAN) of 'ECORDERS.ATTACHMENTS_SOREFITEM' (INDEX)     1  1  6 
13 5 ------NESTED LOOPS 2 1 49 
14 13 -------TABLE ACCESS (BY INDEX ROWID) of 'ECORDERS.ORDERITEMS' (TABLE)     1  3  33 
15 14 --------INDEX (RANGE SCAN) of 'ECORDERS.ORDERITEMS_SOREFITEM02' (INDEX)     1  3  
16 13 -------INDEX (RANGE SCAN) of 'ECUSERS.USERINFO_I_USERNAME_UREFITEM' (INDEX (UNIQUE)) 1  1  38 
ID PA_ID Execution Plan                  COST CARD BYTES 

有什麼辦法可以提高此查詢的性能嗎?

+1

+1包含執行計劃。 –

回答

3

我將尋求做到以下幾點:

  1. 重構爲use ANSI join syntax,對於來自你
  2. 重構,以消除對WHERE子句中的子查詢的需要後,任何人的理智這個 將需要在表中的每一行中執行一次,而不僅僅是您帶回的10個 。
  3. 如果你知道你只將需要10個 行,你可以嘗試添加/*+ FIRST_ROWS(10) */提示給甲骨文 優化了援助之手。
  4. 是必需的嗎?看起來你的大部分工作都是在這裏完成的。
+1

排序是必要的。數據顯示在網頁上,用戶可以根據多列進行排序。 'WHERE'子句根據條件過濾記錄,如果我把它作爲主查詢的一部分,我也沒有得到任何改進。 –

1

我建議用exists條款取代in條款 - 就像這樣:

 AND exists 
      (SELECT null 
      FROM ECOrders.ORDERITEMS ot 
      JOIN ECUSERS.USERINFO USI 
       on OT.OSELLERID = USI.UREFITEM 
       AND UPPER(USI.USERNAME) LIKE UPPER('%Dell Computer%') ESCAPE '~' 
      WHERE ot.sorefitem=so1.sorefitem 
      ) 

的OrderItems之間的連接和USERINFO將是一個內部聯接,因爲你只對戴爾用戶訂購的商品感興趣電腦公司。