我使用以下代码来执行导出数据泵。
set serveroutput on;
DECLARE
ind NUMBER; -- Loop index
h1 NUMBER; -- Data Pump job handle
percent_done NUMBER; -- Percentage of job complete
job_state VARCHAR2(30); -- To keep track of job state
le ku$_LogEntry; -- For WIP and error messages
js ku$_JobStatus; -- The job status from get_status
jd ku$_JobDesc; -- The job description from get_status
sts ku$_Status; -- The status object returned by get_status
>>>>>>>>>>>>>>v_systimestamp TIMESTAMP := SYSTIMESTAMP;<<<<<<<<<<<<<<
BEGIN
h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'EXAMPLE3','LATEST');
DBMS_DATAPUMP.ADD_FILE(h1, 'dumpfile.dmp', 'EXPORT_DIRECTORY', NULL, DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE, 1);
DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''SchemaName'')');
DBMS_DATAPUMP.START_JOB(h1);
percent_done := 0;
job_state := 'UNDEFINED';
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
DBMS_OUTPUT.PUT_LINE(v_systimestamp);
dbms_datapump.get_status(h1,
dbms_datapump.ku$_status_job_error +
dbms_datapump.ku$_status_job_status +
dbms_datapump.ku$_status_wip,-1,job_state,sts);
js := sts.job_status;
-- If the percentage done changed, display the new value.
if js.percent_done != percent_done
then
dbms_output.put_line('*** Job percent done = ' ||
to_char(js.percent_done));
percent_done := js.percent_done;
end if;
-- If any work-in-progress (WIP) or error messages were received for the job,
-- display them.
if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
then
le := sts.wip;
else
if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
then
le := sts.error;
else
le := null;
end if;
end if;
if le is not null
then
ind := le.FIRST;
while ind is not null loop
>>>>>>>>>>>>>>DBMS_OUTPUT.PUT_LINE(v_systimestamp);<<<<<<<<<<<<<<
dbms_output.put_line(le(ind).LogText);
ind := le.NEXT(ind);
end loop;
end if;
end loop;
-- Indicate that the job finished and detach from it.
dbms_output.put_line('Job has completed');
dbms_output.put_line('Final job state = ' || job_state);
dbms_datapump.detach(h1);
END;
问题是导出时间太长。使用此 SQL 代码需要 25 分钟。架构的大小为 1.8 GB。
我想知道各个步骤需要多少时间。这就是为什么我想在每个流程步骤之后插入一个时间戳。然后我可以看到各个步骤需要多长时间。
我已用 (>>>> <<<<) in the code.
标记了时间戳的代码时间戳不更新时间。我需要每个过程后的当前时间。你能帮我吗?
在您的代码中,您在脚本开头设置 v_systimestamp 的值 - 这在整个脚本运行过程中不会改变。您可以在登录之前重置该值,如下所示:
v_systimestamp TIMESTAMP := SYSTIMESTAMP
DBMS_OUTPUT.PUT_LINE(v_systimestamp)
或在要监视的每个部分之前和之后执行类似以下操作(不需要变量):
DBMS_OUTPUT.PUT_LINE('Time Started: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
DBMS_OUTPUT.PUT_LINE('Time Ended: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
这里是“CURRENT_TIMESTAMP”示例
curDateTime TIMESTAMP := CURRENT_TIMESTAMP ;
DBMS_OUTPUT.PUT_LINE('CUR TIME '|| curDateTime);
如果您运行的程序需要很长时间,
DBMS_OUTPUT.PUT_LINE
不会有太大帮助。好吧,它会显示一些内容,但是 - 当您使用循环时,根据迭代次数,DBMS_OUTPUT
可能会耗尽缓冲区大小或超过 SQL*Plus 中的可见行数(如果您使用它),并且您会丢失部分输出。
此外,在该过程完成之前,您不会看到 DBMS_OUTPUT.PUT_LINE
中的任何
字母。
因此,我建议您使用另一种方法 - 简单的日志记录,需要一个表、一个序列和一个(自主事务)过程。这是脚本:
CREATE TABLE a1_log
(
id NUMBER,
datum DATE,
descr VARCHAR2 (500)
);
CREATE SEQUENCE seqlognap START WITH 1 INCREMENT BY 1;
CREATE OR REPLACE PROCEDURE a1_p_log (par_descr IN VARCHAR2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO a1_log
SELECT seqlognap.NEXTVAL, SYSDATE, par_descr FROM DUAL;
COMMIT;
END a1_p_log;
然后将A1_P_LOG调用放入你自己的程序中;类似的东西
begin
a1_p_log('selecting from a large table');
select ... into ... from ...;
a1_p_log('entering the loop');
while ... loop
a1_p_log('doing something');
end loop;
a1_p_log('the end');
end;
这就是自治事务的重要性 - 它会将插入提交到日志表中(不影响主事务),因此您可以(当然,在另一个会话中)跟踪执行情况,只需重复发出
SELECT *
FROM a1_log
ORDER BY id;
它将显示(想象的例子):
1 22.05.2018 18:13:00 selecting from a large table
2 22.05.2018 18:20:07 entering the loop
3 22.05.2018 18:20:07 doing something
4 22.05.2018 18:20:08 doing something
5 22.05.2018 18:20:09 doing something
6 22.05.2018 18:20:10 the end
您会看到步骤 1 需要 7 分钟才能执行,所以 - 这就是您需要调查的内容。这意味着您不必等待主要过程完成 - 取消它并开始解决瓶颈。一旦你修复它,再次运行一切。
声明
“一个”数字:= 5;
“A”数字:= 6;
开始
dbms_output.put_line('a='||a);
dbms_output.put_line('A='||A);
dbms_output.put_line(a);
结束;
为什么输出返回为
a=6
A =6