2017-04-23 108 views
0

我有一個SQL查詢看起來非常簡單。然而,它在生產中表現不佳。任何改善性能的建議將不勝感激。請求優化SQL查詢的提示

SELECT DISTINCT CUSTOMERS.CUST_ID, 
     CUSTOMERS.FNAME, 
     CUSTOMERS.LNAME, 
     CUSTOMERS.CURR_STAT, 
     CUSTOMERS.CREATE_TIME, 
     CUSTOMERS.ROUTE_NBR, 
    FROM CUSTOMERS 
    INNER JOIN 
     INVS 
    ON 
     CUSTOMERS.CUST_ID = INVS.CUST_ID 
    WHERE 
     CUSTOMERS.ROUTE_NBR = 'A10' AND 
     ( 
      CUSTOMERS.LAST_UPD_DT >= ? OR 
      CUSTOMERS.CURR_STAT IN ('PRE' , 'POST' , 'REV') 
     ) AND 
     CUSTOMERS.CURR_STAT NOT IN ('START' , 'END' , 'REJ') AND 
     (
      INVS.INV_CODE = 'AVL' OR 
      INVS.INV_CODE = 'ONORD' 
     ) 

有以下列Customers表上的索引:

  1. ROUTE_NBR
  2. CUST_ID
  3. CREATE_TIME
  4. CURR_STAT

難道做一個顯著如果指數包括LAS,則差異T_UPD_DT列而不是CREATE_TIME列來反映謂詞?任何其他可以改進的地方?謝謝。

+0

是所有四個列或每個索引的索引? –

+0

什麼數據庫?表格中的行數是多少? – ULick

+0

還有沒有其他'CURR_STAT'不在你在查詢中使用的那些6上? –

回答

1

由於您只是從CUSTOMERS表中提取列,我建議使用EXISTS操作來刪除DISTINCT操作。這將是:

SELECT CUSTOMERS.CUST_ID, 
     CUSTOMERS.FNAME, 
     CUSTOMERS.LNAME, 
     CUSTOMERS.CURR_STAT, 
     CUSTOMERS.CREATE_TIME, 
     CUSTOMERS.ROUTE_NBR, 
    FROM CUSTOMERS 
WHERE CUSTOMERS.ROUTE_NBR = 'A10' 
    AND (CUSTOMERS.LAST_UPD_DT >= ? OR 
     CUSTOMERS.CURR_STAT IN ('PRE' , 'POST' , 'REV')) 
    AND CUSTOMERS.CURR_STAT NOT IN ('START' , 'END' , 'REJ') 
    AND EXISTS (SELECT 1 
       FROM INVS 
       WHERE INVS.CUST_ID = CUSTOMERS.CUST_ID 
        AND INVS.INV_CODE IN ('AVL', 'ONORD') 
      ) 

也添加當前查詢的解釋計劃肯定會有所幫助。併爲您的問題if the index included the LAST_UPD_DT column instead of the CREATE_TIME column to reflect the predicates?最有可能的是。

但你知道的確切方法是獲得你實際創建/更改索引的解釋計劃,並將其與新的解釋計劃進行比較。

+1

謝謝,豪爾赫。我將按照您的建議修改查詢,更改索引並從DBA獲取解釋計劃。感謝您的投入! – pdfella

1

我同意豪爾赫有關刪除distinct和使用exists

SELECT c.* -- or whatever 
FROM CUSTOMERS c 
WHERE c.ROUTE_NBR = 'A10' AND 
     (c.LAST_UPD_DT >= ? OR 
     c.CURR_STAT IN ('PRE' , 'POST' , 'REV') 
    ) AND 
     c.CURR_STAT NOT IN ('START' , 'END' , 'REJ') AND 
     EXISTS (SELECT 1 
       FROM INVS 
       WHERE C.CUST_ID = INVS.CUST_ID AND INVS.INV_CODE IN ('AVL', 'ONORD') 

    ); 

那麼對於此查詢,您想對INVS(CUST_ID, INV_CODE)索引和CUSTOMERS(ROUTE_NBR, CURR_STAT, LAST_UPD_DT, CUST_ID)

+0

欣賞您的輸入,戈登!謝謝。 – pdfella