我有一个功能。当我在查询中使用此函数时,通常需要很长时间才能完成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;
答案 0 :(得分:4)
简单的答案(很可能是正确的猜测)是FLOW(CONTRACT_ID)
上的缺失索引。
这将导致每个函数调用中的FULL TABLE SCAN
。
请注意,如果列CONTRACT_ID
的选择性不是很高,则可能需要从函数查询中使用的谓词(例如REVERSAL_STATUS
)中添加其他列。
但是您可能会做得更好-您只需要留在PL / SQL 光标一行一行的日志中并输入SQL方法 >。
这将解决添加索引后仍然存在的另外两个问题:
在调用大量函数的情况下,PL / SQL上下文切换成本很高
您用DIY
实现了一个OUTER JOIN,这要比Oracle慢得多。
从contract_id
到CONTRACT_TEMP
的每个EXPECTED_DT
从FLOW
得到的最小CONTRACT_ID
所需要的id,用函数中的WHERE谓词过滤< / em>。
这可以通过两个步骤完成:
1)为每个EXPECTED_DT
预先计算最小值GROUP BY
-请参阅下面的子查询。请注意,使用LEFT OUTER JOIN
可以一步一步地计算每个合同的结果。
2)将CONTRACT_TEMP
表SELECT 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)