多个联接的Oracle查询优化

时间:2015-03-12 09:29:57

标签: sql oracle

以下查询花费的时间太长(30秒)。 我认为瓶颈在where子句中。有可能优化吗?

SELECT
    COUNT(*) AS IN_HELP
FROM
    HCM.TableA
INNER JOIN
    HCM.EMPLOYEE_POSITION_BOX EPB
ON
    TableA.POSITION_BOX_CODE = EPB.POSITION_BOX_CODE AND NVL (V_DATE,SYSDATE) BETWEEN EPB.EFFECTIVE_DATE AND EPB.END_DATE
LEFT OUTER JOIN
    HCM.NODE_LEVEL_MASTER NLM
ON
    HCM.F_EMPLOYEE_ACTUAL_NODE(EPB.EMPLOYEE_CODE,TRUNC(SYSDATE)) = NLM.NODE_NO
LEFT JOIN
    HCM.POSITION_STATUS_MASTER PSM
ON
    TableA.STATUS = PSM.POSITION_STATUS_NO
WHERE
    NLM.NODE_NO_LEVEL2 = V_LOOP.NODE_NO_LEVEL2
    AND HCM.F_EMPLOYEE_ACTUAL_NODE(EPB.EMPLOYEE_CODE,TRUNC (SYSDATE)) <> TableA.NODE_NO
    AND PSM.FLAG = 'Y'
    AND TableA.STATUS <> '0108'

2 个答案:

答案 0 :(得分:1)

首先,从WHERE子句检查表的索引:

  • NLM.NODE_NO_LEVEL2
  • V_LOOP.NODE_NO_LEVEL2
  • TableA.NODE_NO
  • TableA.STATUS

PSM.FLAG不应该添加到索引中,因为它不会对表中的数据进行有效过滤。

另外,我是对的,HCM.F_EMPLOYEE_ACTUAL_NODE是一个功能吗?如果是这样,那么您应该考虑将其从WHERE子句中删除,因为执行计划不会检查内部查询,并且它根本没有被优化,这会导致性能问题。

答案 1 :(得分:1)

主要问题是您的功能HCM.F_EMPLOYEE_ACTUAL_NODE。首先将函数调用移到子查询(epbx):

SELECT
    COUNT(*) AS IN_HELP
FROM
    HCM.TableA
INNER JOIN
    (SELECT HCM.F_EMPLOYEE_ACTUAL_NODE(EPB.EMPLOYEE_CODE,TRUNC(SYSDATE)) node, epb.* from HCM.EMPLOYEE_POSITION_BOX EPB) epbx
ON
    TableA.POSITION_BOX_CODE = EPBx.POSITION_BOX_CODE AND NVL (V_DATE,SYSDATE) BETWEEN EPBx.EFFECTIVE_DATE AND EPBx.END_DATE
LEFT OUTER JOIN
    HCM.NODE_LEVEL_MASTER NLM
ON
    epbx.node = NLM.NODE_NO
LEFT JOIN
    HCM.POSITION_STATUS_MASTER PSM
ON
    TableA.STATUS = PSM.POSITION_STATUS_NO
WHERE
    NLM.NODE_NO_LEVEL2 = V_LOOP.NODE_NO_LEVEL2
    AND epbx.node <> TableA.NODE_NO
    AND PSM.FLAG = 'Y'
    AND TableA.STATUS <> '0108'

然后使用解释计划来确定您的查询是否有效写入。