我有一个看起来相当简单的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表上有一个索引:
如果索引包含LAST_UPD_DT列而不是CREATE_TIME列来反映谓词,它会产生显着差异吗?可以做出任何其他改进吗?谢谢。
答案 0 :(得分: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 :(得分:1)
我同意Jorge关于删除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)
上的索引。