【发布时间】:2019-05-25 06:56:19
【问题描述】:
我们使用的是 Oracle 11.2.0.4.0。 我们创建了一个过程来更新表中所有可用行的 CLOB 列。
我们有一个 DBMS_OUTPUT.PUT_LINE 语句用于在过程的最后一行打印 SYSDATE。
当我们执行这个过程时,在最后一行打印完 SYSDATE 之后需要很长时间才能完成。
不确定我是否遗漏了什么。任何帮助将不胜感激
我们尝试通过在过程中添加DBMS_OUPUT.PUT_LINE(SYSDATE) 语句来调试/查找痛点来执行过程。
这就是我们执行过程并在最后粘贴输出的方式:
SET TIMING ON
SET SERVEROUTPUT ON
SELECT 'Outside block Start time: ' || to_char(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') OUTSIDEBLOCKSTARTTIME from dual;
DECLARE
I_LIMIT BINARY_INTEGER;
I_STR_TO_REPLACE VARCHAR2(200);
I_REPLACEMENT_STR VARCHAR2(200);
BEGIN
I_LIMIT := 10000;
I_STR_TO_REPLACE := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
I_REPLACEMENT_STR := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
P_TEST_CLOB_MASK(
I_LIMIT => I_LIMIT,
I_STR_TO_REPLACE => I_STR_TO_REPLACE,
I_REPLACEMENT_STR => I_REPLACEMENT_STR
);
END;
/
SELECT 'Outside block End time: ' || to_char(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') OUTSIDEBLOCKENDTIME from dual;
下面是过程的代码:
CREATE OR REPLACE PROCEDURE p_test_clob_mask (
i_limit IN PLS_INTEGER DEFAULT 1000,
i_str_to_replace IN VARCHAR2
DEFAULT 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890',
i_replacement_str IN VARCHAR2
DEFAULT 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'
)
IS
CURSOR cur_fetch_cddaddcomphistory
IS
SELECT ROWID row_id, ua4cf_cddaddcomphistory ua4cf_cddaddcomphistory
FROM generic_set11
WHERE ua4cf_cddaddcomphistory IS NOT NULL;
l_limit NUMBER := 0;
l_counter NUMBER := 0;
l_rowid ROWID;
l_hold_clob CLOB;
l_masked_clob CLOB;
l_length_clob NUMBER := 0;
l_str_to_replace VARCHAR2 (500);
l_replacement_str VARCHAR2 (500);
l_overall_start_dt DATE;
l_batch_start_dt DATE := NULL;
l_batch_time_taken NUMBER := 0;
l_overall_time_taken NUMBER := 0;
BEGIN
l_overall_start_dt := SYSDATE;
DBMS_OUTPUT.put_line ( 'Overall Start: '
|| TO_CHAR (l_overall_start_dt,
'DD-MON-RR HH24:MI:SS'
)
);
l_str_to_replace := i_str_to_replace;
l_replacement_str := i_replacement_str;
l_limit := i_limit;
OPEN cur_fetch_cddaddcomphistory;
LOOP
FETCH cur_fetch_cddaddcomphistory
INTO l_rowid, l_hold_clob;
EXIT WHEN cur_fetch_cddaddcomphistory%NOTFOUND;
l_counter := l_counter + 1;
l_length_clob := DBMS_LOB.getlength (l_hold_clob);
DBMS_LOB.createtemporary (l_masked_clob, TRUE);
DBMS_LOB.writeappend (l_masked_clob,
l_length_clob,
TRANSLATE (l_hold_clob,
i_str_to_replace,
i_replacement_str
)
);
UPDATE generic_set11
SET ua4cf_cddaddcomphistory = l_masked_clob
WHERE ROWID = l_rowid;
IF MOD (l_counter, l_limit) = 0
THEN
COMMIT;
END IF;
END LOOP;
CLOSE cur_fetch_cddaddcomphistory;
COMMIT;
l_overall_time_taken :=
TRUNC (((SYSDATE - l_overall_start_dt) * 24 * 60), 2);
DBMS_OUTPUT.put_line ( 'Overall End: '
|| TO_CHAR (SYSDATE, 'DD-MON-RR HH24:MI:SS')
|| ' - Time taken in Mins: '
|| l_overall_time_taken
|| ' - Counters: '
|| l_counter
);
END p_test_clob_mask;
/
我们的期望是在最后一个DBMS_OUPUT.PUT_LINE完成后,该过程应该完成。
但经过的时间说 20 多分钟,而根据最后的DBMS_OUPUT.PUT_LINEstatement,所用时间仅为 3 分钟
下面是输出:
OUTSIDEBLOCKSTARTTIME
-------------------------------------------------------
Outside block Start time: 27-DEC-2018 15:33:45
Elapsed: 00:00:00.118
Overall Start: 27-DEC-18 15:33:45
Overall End: 27-DEC-18 15:37:37 - Time taken in Mins: 3.86 - Counters: 138913
PL/SQL procedure successfully completed.
Elapsed: 00:20:19.313
OUTSIDEBLOCKENDTIME
-----------------------------------------------------
Outside block End time: 27-DEC-2018 15:54:04
Elapsed: 00:00:00.095
【问题讨论】:
-
在我看来,您好像在创建很多临时的
CLOBs。如果您使用DBMS_LOB.FREETEMPORARY释放它们会有所帮助吗? -
另一种想法是在循环外创建一个临时的
CLOB,并在每次循环迭代的开始(或结束)删除它。 -
@LukeWoodward 你成功了。我在循环中添加了
DBMS_LOB.freetemporary (l_masked_clob);。现在程序在最后一个DBMS_OUTPUT.PUT_LINE被执行后立即完成谢谢你的帮助。
标签: oracle plsql oracle11g execution-time