到文件的Oracle斑点批量提取 - 咨询/调整需要帮助(Bulk extraction of Or

2019-09-17 01:34发布

我的工作需要现有的Oracle斑点迁移到文件的项目。 从阅读环境是共享的Oracle 10gR2中的服务器。 目前,我有使用UTL_FILE的脚本。 然而,这个过程是相当缓慢。 这需要3小时左右,以提取样本数据的25 GB。 要移动的实际数据是在1个TB的顺序。 我需要显著调整帮助/建议。

这里是我的过程:

  1. 打开游标来获取BLOB ID和姓名的列表
  2. 启动了一个循环来通每个斑
  3. 提取使用BLOB2FILE,自定义存储过程中的BLOB(从网站把它捡起来,并修改了它略)

这里是代码:

create or replace
PROCEDURE BLOB2File(
    lngBlobID IN NUMBER,
    sFileName IN VARCHAR2,
    sDir      IN VARCHAR2)
AS
  iFileLen INTEGER;
  iLineLen INTEGER := 32000; -- max line size for utl_file
  vStart   NUMBER  := 1;
  vBlob BLOB;
  l_output utl_file.file_type;
  my_vr RAW(32000);
  iTmp INTEGER;
BEGIN
  -- get blob details
  LOG_IT('Entered. Blob Id: ' || lngBlobID || ', File Name: ' || sFileName || ', Directory: ' || sDir);
  SELECT blobData,
    lengthb(blobData)
  INTO vBlob,
    iFileLen
  FROM blobTable
  WHERE id = lngBlobID;
  LOG_IT('Acquired the blob. Blob size: ' || TO_CHAR(iFileLen));
  l_output := utl_file.fopen(sDir, sFileName,'wb', iLineLen);
  vStart   := 1;
  iTmp     := iFileLen;
  -- if small enough for a single write
  IF iFileLen < iLineLen THEN
    utl_file.put_raw(l_output,vBlob);
    utl_file.fflush(l_output);
  ELSE -- write in pieces
    vStart      := 1;
    WHILE vStart < iFileLen AND iLineLen > 0
    LOOP
      dbms_lob.read(vBlob,iLineLen,vStart,my_vr);
      utl_file.put_raw(l_output,my_vr);
      utl_file.fflush(l_output);
      -- set the start position for the next cut
      vStart := vStart + iLineLen;
      -- set the end position if less than 32000 bytes
      iTmp       := iTmp - iLineLen;
      IF iTmp     < iLineLen THEN
        iLineLen := iTmp;
      END IF;
    END LOOP;
  END IF;
  utl_file.fclose(l_output);
  LOG_IT('Exited');

  EXCEPTION
  WHEN OTHERS THEN
  LOG_IT('**ERROR** ' || SQLERRM, SQLCODE, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;

LOG_IT是一个存储过程记录到一个表。 不应该有任何显著命中那里。 我试图通过使用BULK FETCH代替一个正常的FETCH优化步骤1。 然而,它并没有产生任何显著的结果。

任何人都可以提出改进或任何想法甚至更好,这接近一个更好的性能呢?

Answer 1:

假设你的硬件足以应付远远超过持续8 GB /小时写sDir (和处理读取从类似的量blobTable和处理任何其他I / O系统的需求),最简单的选择将可能是产卵其中的每一个调用这个过程的几个平行会议。 例如,如果你想同时运行三个作业其中每个被提取一个LOB,你可以做这样的事情。

DECLARE
  l_jobno INTEGER;
BEGIN
  dbms_job.submit( l_jobno, 'begin BLOB2File( 1, ''1.lob'', ''DIRECTORY'' ); end;', sysdate + interval '5' second );
  dbms_job.submit( l_jobno, 'begin BLOB2File( 2, ''2.lob'', ''DIRECTORY'' ); end;', sysdate + interval '5' second );
  dbms_job.submit( l_jobno, 'begin BLOB2File( 3, ''3.lob'', ''DIRECTORY'' ); end;', sysdate + interval '5' second );
  commit;
END;

你可能不希望有在reality--你可能要产生的就业岗位数量较少,并给他们每人一个范围内的每一个BLOB一个单独的线程lngBlobID值去努力。 Oracle将在任何时间运行的作业数由有限JOB_QUEUE_PROCESSES参数,所以你可以提交作业十万,只是让甲骨文限制多少会同时运行。



文章来源: Bulk extraction of Oracle BLOBS into files - advice/tuning help needed