Export with Spool and Parallel Utl_File

chncaesar發表於2013-11-12
Dump with SPOOL
set trimspool on --removes trailing blanks at the end of each displayed or spooled line.
set feedback off --Do not display the number of records returned by a query
set termout off  --Do not display the output generated by commands executed from a script.
set pages 0 --to suppress all headings, page breaks, titles, the initial blank line, and other formatting information.
set echo off --Suppresses the display of echo commands in a script that is executed with @, @@ or START.
set line 150
set arraysize 300 
spool   /home/oracle/data/out.csv
select /*+ parallel(8) */ 
x || ',' ||
x
FROM dual
where 1=0
;
spool off

DUMP with Parallelized Utl_File
Obviously, I/O is the bottleneck here. A dump program that writes to several files simultaneously would greatly fasten the process. Here's an example which utilizes parallel pipelined function and utl_file.
However, in this case,  data is dumped on the server side, you need to download dump file from Oracle server, while spool output file stays on local machine.

CREATE SEQUENCE dump_seq;

CREATE TYPE dump_ot AS OBJECT ( 
      file_name  VARCHAR2(128), 
      no_records NUMBER      
);
  
CREATE TYPE dump_ott AS TABLE OF dump_ot;

CREATE OR REPLACE FUNCTION my_dump(p_input_cur SYS_REFCURSOR, p_file VARCHAR2)
  return dump_ott
  PIPELINED
  PARALLEL_ENABLE (PARTITION p_input_cur BY ANY)   
AS
  TYPE row_ntt IS TABLE OF VARCHAR2(32767);
  v_rows    row_ntt;

  v_file   utl_file.file_type;
  v_buffer VARCHAR2(32767);  
  v_num_lines   PLS_INTEGER := 0;
  v_name    VARCHAR2(128);
  c_eol     CONSTANT VARCHAR2(1) := CHR(10);
  c_eollen  CONSTANT PLS_INTEGER := LENGTH(c_eol);
  c_maxline CONSTANT PLS_INTEGER := 32767;
BEGIN
  v_name := p_file || dump_seq.nextval || '.dat';
  v_file := utl_file.fopen(LOCATION => 'EXT_DAT_DIR', filename => v_name, open_mode => 'w', max_linesize => 32767);
  
  LOOP
    FETCH p_input_cur BULK COLLECT INTO v_rows LIMIT 500;
    
    FOR i IN v_rows.FIRST .. v_rows.LAST LOOP
    
      IF LENGTH(v_rows(i)) + c_eollen + LENGTH(v_buffer) <= c_maxline THEN
        v_buffer := v_buffer || c_eol || v_rows(i);
      ELSE
        IF v_buffer IS NOT NULL THEN
          utl_file.put_line(v_file, v_buffer);
        END IF;
        v_buffer := v_rows(i);
      END IF;
      
    END LOOP;
    v_num_lines := v_num_lines + v_rows.COUNT;  
    EXIT WHEN p_input_cur%NOTFOUND;
  END LOOP;
  CLOSE p_input_cur;
  
  UTL_FILE.PUT_LINE(v_file, v_buffer);
  UTL_FILE.FCLOSE(v_file);
  
  PIPE ROW (dump_ot(v_name, v_num_lines));
  RETURN;
END;
經測試,該方法會造成各行之間序列。需要修正程式。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/638844/viewspace-776394/,如需轉載,請註明出處,否則將追究法律責任。

相關文章