2017-04-23 40 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