此过程编译良好,但是要花很多时间才能运行。我认为即使是单行处理,也要花费太多时间。我应该在哪里更改代码以使其运行更快?
CREATE OR REPLACE PROCEDURE NEWWAPTWOPROC(
P_WAP NUMBER,
P_DEALNO VARCHAR2,
P_FDT DATE,
P_SECURITYCD VARCHAR2,
P_SECURITYTYPE VARCHAR2,
P_SELFORCONSTITUENT VARCHAR2
)
IS
v_pofv NUMBER(30);
v_sofv NUMBER(30);
CURSOR C1 IS
SELECT
D.SECURITYCD SCD,
D.DEALNO DNO,
S.OWNSTK OWNST,
LAG(S.OWNSTK) OVER(ORDER BY D.DEALDT) PC_STK,
D.Dealtype DTYPE,
D.SECURITYTYPE STYPE,
D.SELFORCONSTITUENT SFORCO,
D.DEALDT DDATE ,
D.PRICE PRC,
D.FACEVALUE FV,
LAG(D.FACEVALUE) OVER(ORDER BY D.DEALDT) PC_FV,
D.WAP1 WP,
LAG(D.WAP1) OVER(ORDER BY D.DEALDT) PC_WAP1
FROM MMDEAL0_NWAP D INNER JOIN Mmstock1 S
ON D.Securitycd=S.Securitycd
WHERE D.DEALDT>=P_FDT
AND D.DEALNO=P_Dealno
AND D.FACEVALUE>0
AND D.Dealtype IN('PO','SO')
AND D.Selforconstituent='S'
AND D.SECURITYTYPE='DGS'
ORDER BY
D.DEALDT,D.Securitycd;
BEGIN
FOR i in C1
LOOP
if C1%rowcount=1 then
UPDATE MMDEAL0_NWAP SET WAP1=P_WAP WHERE Dealno=P_DEALNO AND DEALDT=P_FDT AND
SECURITYCD=P_SECURITYCD AND SECURITYTYPE=P_SECURITYTYPE AND
Selforconstituent=P_SELFORCONSTITUENT;
else
IF i.OWNST>0 then
if i.DTYPE='PO' then
v_pofv:=i.FV;
elsif i.DTYPE='SO' then
v_sofv:=i.FV;
end if;
i.WP:=((nvl(i.PC_WAP1,0)*nvl(i.PC_STK,0))+(nvl(v_pofv,0)*nvl(i.PRC,0)))-(nvl(v_sofv,0)*nvl(i.PC_WAP1,0))/i.OWNST;
UPDATE MMDEAL0_NWAP SET WAP1=i.WP WHERE DEALNO=i.DNO AND DEALDT=i.DDATE AND
SECURITYCD=i.SCD AND SECURITYTYPE=i.STYPE AND SELFORCONSTITUENT= i.SFORCO;
END IF;
end if;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
Dbms_Output.Put_Line(SQLCODE||' '||SQLERRM);
END NEWWAPTWOPROC;
答案 0 :(得分:3)
您正在使用CURSOR
并在所有更新都可以转换为更新和MERGE
语句时无故循环。
以下是您对案例C1%rowcount=1
的更新声明,甚至在之前也不需要将其放入循环中。
UPDATE mmdeal0_nwap
SET wap1 = p_wap
WHERE dealno = p_dealno
AND dealdt = p_fdt
AND securitycd = p_securitycd
AND securitytype = p_securitytype
AND selforconstituent = p_selforconstituent;
第二次更新已转换为MERGE
MERGE INTO mmdeal0_nwap t USING (
SELECT i.*,
( ( nvl(i.pc_wap1,0) * nvl(i.pc_stk,0) ) + ( nvl(v_pofv,0) * nvl(i.prc,0) ) ) - ( nvl(v_sofv
,0) * nvl(i.pc_wap1,0) ) / i.ownst AS new_wp --your calculation for the value of WP to be updated
FROM (
SELECT d.securitycd scd,
d.dealno dno,
s.ownstk ownst,
LAG(s.ownstk) OVER(
ORDER BY d.dealdt
) pc_stk,
d.dealtype dtype,
d.securitytype stype,
d.selforconstituent sforco,
d.dealdt ddate,
d.price prc,
d.facevalue fv,
LAG(d.facevalue) OVER(
ORDER BY d.dealdt
) pc_fv,
d.wap1 wp,
LAG(d.wap1) OVER(
ORDER BY d.dealdt
) pc_wap1,
CASE
WHEN d.dealtype = 'PO' THEN d.facevalue
END
AS v_pofv,
CASE
WHEN d.dealtype = 'SO' THEN d.facevalue -- IF conditions converted to CASE
END
AS v_sofv
FROM mmdeal0_nwap d
INNER JOIN mmstock1 s ON d.securitycd = s.securitycd
WHERE d.dealdt >= p_fdt AND d.dealno = p_dealno AND d.facevalue > 0 AND d.dealtype IN (
'PO',
'SO'
) AND d.selforconstituent = 'S' AND d.securitytype = 'DGS'
) i
WHERE i.ownst > 0 --outer IF condition
)
ON (
t.dealno = s.dno AND t.dealdt = s.ddate AND t.securitycd = s.scd AND t.securitytype = s.stype AND
t.selforconstituent = s.sforco
) --where clause from your update
WHEN MATCHED THEN UPDATE SET t.wap1 = s.new_wp;
请注意,代码是 unested ,因此您可能必须修复一些我可能犯的语法错误/编辑错误。但是,我相信我已经给了您足够的想法,该如何进行。
答案 1 :(得分:0)
有关调查PL / SQL性能的一些一般建议:
dbms_output
条包含计数和计时的消息(或将详细信息写入日志表)。如果代码永远不会完成或产生太多输出,这可能会很棘手,但是您可以创建一些简化的测试数据来限制运行。dbms_profiler
获取有关每个语句被调用多少次以及花费多少时间的报告。同样,您可能需要使用简化的测试数据来限制运行。性能分析内置于某些桌面工具(例如PL / SQL Developer)中,因此您只需单击一个按钮,否则就可以在命令行中直接使用它。 (还有dbms_hprof
,虽然使用起来几乎没有好处,但还有dbms_trace
,尽管以我的经验,这并不能告诉您任何有用的信息。)v$session
来了解很多事情。某些台式机工具内置有会话监视器,以使此操作变得更容易。
v$active_session_history
中获得很多有用的运行时信息。