我在 11g 和 12c Oracle 系统上运行。我对即将编写的一些 PL/SQL 有疑问。我一直在进行广泛的研究,但我不太清楚答案,并希望从论坛中获得一些意见。我的主要目标是保持高水平的表现。在处理这些数据时,我试图避免上下文切换。
SP的目的是批量join来自2个不同表的一组数据,操作集合中的一组字段并将其写入不同Instance中的另一个表。我显然希望在 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 - PLSQL 上下文切换,它的成本要高得多,尤其是因为它将在每行返回时切换。 FORALL 循环可以替代内存中针对内存中的表的常规 for 循环。这应该仍然非常快。如果您想使用 FORALL 批量插入,您可以将插入从“for 循环”中取出,但对于额外的开销,我认为它不会有太大区别。
至于批量处理所有事情——我的建议是,对于“数亿”行——取决于表格的“厚度/厚度”——你肯定会破坏你的 PGA 并对数据库中的区域大小进行排序,除非你有一个非常善良的 DBA,他会为您提供所需的所有内存(值得怀疑)。作为一般规则,我尽量不要在内存中放置超过 2-5 百万行。
declare
l_complex number; -- dont know the real datatype here??
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
FOR indx IN vTable.FIRST .. vTable.LAST loop
l_complex : = COMPLX_CALC_FUNCTION(vtable(indx).TR_TM,vtable(indx).TR_CD );
INSERT INTO Table2 VALUES vTable(indx);
end loop;
...
--ending stuff
;
关于oracle - 操作 BULK COLLECT 数据时,存储过程中是否会发生上下文切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35397747/