监控长时间运行的 PL/SQL 块

发布于 2024-12-03 11:53:43 字数 360 浏览 5 评论 0原文

我有一个相当耗时的 PL/SQL 块,它可以根据分子结构构建指纹。我想将输出打印到 SQL*Plus 控制台,以提供有关已处理的结构数量的反馈。我可以使用 dbms_output.put_line 来完成此操作,

但是每次调用都会写入新行。我想覆盖该行。

例如,目前我有以下内容。

Structure x of y processed
Structure x of y processed
Structure x of y processed
Structure x of y processed

最终,当我处理数千条结构记录时,我填满了缓冲区。

我可以使用一种方法来覆盖最后一个输出行吗?

I have a fairly time intensive PL/SQL block that builds fingerprints from molecular structures. I would like to print output to SQL*Plus console to provide feedback on how many structures have been processed. I can do this with dbms_output.put_line

However everytime that is called a new line is written. I want to overwrite the line.

For example, currently I have the below.

Structure x of y processed
Structure x of y processed
Structure x of y processed
Structure x of y processed

Eventually I fill up the buffer as I'm dealing with thousands of structure records.

Is there a method I can use that will just overwrite the last output line?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

饮湿 2024-12-10 11:53:43

使用 DBMS_OUTPUT 意味着 SQL*Plus 在整个 PL/SQL 块完成之前不会显示任何内容,然后显示缓冲区中当前的所有数据。因此,这不是提供持续状态的适当方式。

另一方面,Oracle 确实提供了一个专门为帮助您而设计的包 DBMS_APPLICATION_INFO监视您正在运行的代码。例如,您可以执行以下操作:

CREATE PROCEDURE process_structures
AS
  <<other variable declarations>>

  rindex    BINARY_INTEGER;
  slno      BINARY_INTEGER;
  totalwork NUMBER := y; -- Total number of structures
  worksofar NUMBER := 0; -- Number of structures processed
BEGIN
  rindex := dbms_application_info.set_session_longops_nohint;

  FOR i IN (<<select structures to process>>)
  LOOP
    worksofar := worksofar + 1;
    dbms_application_info.set_session_longops(
        rindex      => rindex, 
        slno        => slno,
        op_name     => 'Processing of Molecular Structures', 
        sofar       => worksofar , 
        totalwork   => totalwork, 
        target_desc => 'Some description',
        units       => 'structures');
    <<process your structure with your existing code>>
  END LOOP;
END;

从单独的 SQL*Plus 会话中,您可以通过查询 V$SESSION_LONGOPS 视图来监视进度

SELECT opname,
       target_desc,
       sofar,
       totalwork,
       units,
       elapsed_seconds,
       time_remaining
  FROM v$session_longops
 WHERE opname = 'Processing of Molecular Structures';

Using DBMS_OUTPUT means that SQL*Plus will display nothing until the entire PL/SQL block is complete and will then display all the data currently in the buffer. It is not, therefore, an appropriate way to provide an ongoing status.

On the other hand, Oracle does provide a package DBMS_APPLICATION_INFO that is specifically designed to help you monitor your running code. For example, you could do something like

CREATE PROCEDURE process_structures
AS
  <<other variable declarations>>

  rindex    BINARY_INTEGER;
  slno      BINARY_INTEGER;
  totalwork NUMBER := y; -- Total number of structures
  worksofar NUMBER := 0; -- Number of structures processed
BEGIN
  rindex := dbms_application_info.set_session_longops_nohint;

  FOR i IN (<<select structures to process>>)
  LOOP
    worksofar := worksofar + 1;
    dbms_application_info.set_session_longops(
        rindex      => rindex, 
        slno        => slno,
        op_name     => 'Processing of Molecular Structures', 
        sofar       => worksofar , 
        totalwork   => totalwork, 
        target_desc => 'Some description',
        units       => 'structures');
    <<process your structure with your existing code>>
  END LOOP;
END;

From a separate SQL*Plus session, you can then monitory progress by querying the V$SESSION_LONGOPS view

SELECT opname,
       target_desc,
       sofar,
       totalwork,
       units,
       elapsed_seconds,
       time_remaining
  FROM v$session_longops
 WHERE opname = 'Processing of Molecular Structures';
碍人泪离人颜 2024-12-10 11:53:43

您还可以将消息发送到命名管道,并让另一个进程从管道中读取消息。

   procedure sendmessage(p_pipename varchar2
                        ,p_message  varchar2) is
      s number(15);
   begin
      begin
         sys.dbms_pipe.pack_message(p_message);
      exception
         when others then
            sys.dbms_pipe.reset_buffer;
      end;

      s := sys.dbms_pipe.send_message(p_pipename, 0);

      if s = 1
      then
         sys.dbms_pipe.purge(p_pipename);
      end if;
   end; 


   function receivemessage(p_pipename varchar2
                          ,p_timeout  integer) return varchar2 is
      n   number(15);
      chr varchar2(200);
   begin
      n := sys.dbms_pipe.receive_message(p_pipename, p_timeout);

      if n = 1
      then
         return null;
      end if;

      sys.dbms_pipe.unpack_message(chr);
      return(chr);
   end;

You may also send messages to a named pipe and have another process read the message from the pipe.

   procedure sendmessage(p_pipename varchar2
                        ,p_message  varchar2) is
      s number(15);
   begin
      begin
         sys.dbms_pipe.pack_message(p_message);
      exception
         when others then
            sys.dbms_pipe.reset_buffer;
      end;

      s := sys.dbms_pipe.send_message(p_pipename, 0);

      if s = 1
      then
         sys.dbms_pipe.purge(p_pipename);
      end if;
   end; 


   function receivemessage(p_pipename varchar2
                          ,p_timeout  integer) return varchar2 is
      n   number(15);
      chr varchar2(200);
   begin
      n := sys.dbms_pipe.receive_message(p_pipename, p_timeout);

      if n = 1
      then
         return null;
      end if;

      sys.dbms_pipe.unpack_message(chr);
      return(chr);
   end;
落花浅忆 2024-12-10 11:53:43

我认为你不能。据我了解 dbms_output 它只是不能那样工作。

我建议您使用 put 每隔 1000 个左右的条目回显一个点和一个换行符,以查看正在发生的情况,并将当前位置写入表中或对当前位置进行排序,以便您可以查看是否想知道。

I don't think you can. As far as I understood the dbms_output it just doesn't work that way.

I recommend you use put to echo a single dot and a newline every 1000 or so entries to see that something is happening and write into a table or sequence the current position so you can have a look if you want to know.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文