【发布时间】:2016-02-14 20:42:38
【问题描述】:
我在 11g 和 12c Oracle 系统上运行。我对即将写的一些 PL/SQL 有疑问。我一直在进行广泛的研究,但我并没有完全看到答案,并希望从论坛中获得一些意见。我的主要目标是保持高水平的性能。在处理这些数据时,我试图避免上下文切换。
SP 的目的是批量连接来自 2 个不同表的一组数据,操作集合中的一组字段并将其写入不同实例中的另一个表。我显然想在 BULK 中尽可能多地做,但我不确定在我完成它时,由于复杂的字段操作,我是否最终不会进行某种单行上下文切换。
详情如下:
声明一个将执行内部连接的游标。在 SELECT 中我想做一些数据操作。我想调用一个函数来执行此操作,因为尝试在 select 语句中执行此操作会非常混乱:
CURSOR c1 is
SELECT DISTINCT A.ID,
A.PT_NBR,
A.PT_DT,
A.PT_QTY,
(COMPLX_CALC_FUNCTION(B.TR_TM,B.TR_CD ) nRESULT
FROM PT_TABLE A
INNER JOIN TRAN_TABLE B
ON (A.PT_NBR = B.TRAN_NBR
AND A.PT_DT = B.TRAN_DT
AND A.PT_DT BETWEEN B.START_DT AND B.END_DT)
WHERE A.ID = vID;
结果将是数十万或数百万条记录,所以我想批量处理
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO vTable LIMIT 20000;
---body code
-- trying to avoid additional manipulation of the data here but there may still be some
FORALL indx IN vTable.FIRST .. vTable.LAST
...
INSERT INTO Table2 VALUES vTable(indx);
--ending stuff
;
COMPLX_CALC_FUNCTION 将接受输入并执行数学运算并调用其他函数,例如 NVL、SUM 和 CEIL。
所以,问题是……我是否会因为光标选择中的函数调用而受到上下文切换的影响,或者我是否需要操作 SP 主体中的数据?此外,对于这种情况,我还需要考虑其他性能方面的事情吗?我试图避免将数据转储到临时物理表中并对其进行操作,因为这似乎比在内存中执行要慢得多。感谢您的专家建议。
【问题讨论】:
-
简而言之,是的。在 SQL 和 PL/SQL 引擎之间会有一个上下文切换,根据 Tom Kyte 的说法,这是一个 nasty 类型的切换。如果你真的想避免它,从循环体内部调用函数,或者尽可能使用 SQL 和原生函数来实现你的逻辑。
-
你能给出这个“COMPLX”函数的定义吗?这个函数是否只对其参数执行简单的计算?或者该函数是否在其主体中调用了一些 SQL 语句(SELECT、UPDATE 等),这些语句会导致从 PL/SQL 到 SQL 引擎的额外上下文切换?您能否告诉我们表 A 和 B 之间的关系是 1-1 还是 1-n,我的意思是,如果来自 A 和 B 的两条记录的连接总是只产生 1 条记录,(1-1),或者可能产生许多记录 (1-n) ?
-
是的,函数执行基本计算,例如:BEGIN IF TR_CD = '6' OR TR_CD = '7' THEN real_days := TR_CD; ELSE real_days := '5';万一; tr_pct := MOD(real_weeks := (NVL(TR_TM, 0) / 24) / real_days, 1); real_weeks := real_weeks - tr_pct;返回 real_weeks;