为什么此查询需要很长时间才能完成?

时间:2019-01-03 09:14:42

标签: oracle oracle11g oracle10g

我有一个功能。当我在查询中使用此函数时,通常需要很长时间才能完成1到2个小时。这是我的第一个查询...

SELECT GET_DAYSNS_SF(CONTRACT_ID) 
FROM   CONTRACT_TEMP;

和功能...

CREATE OR REPLACE FUNCTION GET_DAYSNS_SF
    (CONTRACT_ID IN NUMBER)
    RETURN DATE
AS
    CONTRACT_ID1 NUMBER(16) := CONTRACT_ID;
    DAYSNS DATE;

BEGIN
  BEGIN
    SELECT MIN(EXPECTED_DT)
    INTO DAYSNS
    FROM FLOW
    WHERE REVERSAL_STATUS = 4200
    AND FLOW_TYPE IN(1003,1006,1027)
    AND IS_CASH = 1
    AND AMOUNT > 0
    AND AMOUNT > NVL(AMT_MATCHED,0)
    AND CONTRACT_ID = CONTRACT_ID1;
 EXCEPTION 
    WHEN NO_DATA_FOUND THEN
       DAYSNS := NULL;
  END;
  RETURN DAYSNS;
END;

2 个答案:

答案 0 :(得分:4)

简单的答案(很可能是正确的猜测)是FLOW(CONTRACT_ID) 上的缺失索引。

这将导致每个函数调用中的FULL TABLE SCAN

请注意,如果列CONTRACT_ID的选择性不是很高,则可能需要从函数查询中使用的谓词(例如REVERSAL_STATUS)中添加其他列。

但是您可能会做得更好-您只需要留在PL / SQL 光标一行一行的日志中输入SQL方法 >。

这将解决添加索引后仍然存在的另外两个问题

  • 在调用大量函数的情况下,PL / SQL上下文切换成本很高

  • 您用DIY实现了一个OUTER JOIN,这要比Oracle慢得多。

contract_idCONTRACT_TEMP的每个EXPECTED_DTFLOW得到的最小CONTRACT_ID所需要的id,用函数中的WHERE谓词过滤< / em>。

这可以通过两个步骤完成:

1)为每个EXPECTED_DT预先计算最小值GROUP BY-请参阅下面的子查询。请注意,使用LEFT OUTER JOIN可以一步一步地计算每个合同的结果。

2)将CONTRACT_TEMPSELECT f.EXPECTED_DT FROM CONTRACT_TEMP c LEFT OUTER JOIN (SELECT CONTRACT_ID, MIN(EXPECTED_DT) EXPECTED_DT FROM FLOW WHERE REVERSAL_STATUS = 4200 AND FLOW_TYPE IN(1003,1006,1027) AND IS_CASH = 1 AND AMOUNT > 0 AND AMOUNT > NVL(AMT_MATCHED,0) GROUP BY CONTRACT_ID) f on c.CONTRACT_ID = f.CONTRACT_ID 移至1)的结果

查询-等同于您的初始查询:

from pyspark.sql.functions import col
data.groupby("card_bank", "failed").count().filter(col("failed") == "true").collect()[0]["count"]

答案 1 :(得分:0)

您可以删除条件AND AMOUNT > 0,因为查询已经具有另一个类似的条件AMOUNT > NVL(AMT_MATCHED,0)