我需要从oracle数据库导出多达2亿个blob到基于linux的目录作为图像。将映像导出到目录后,Oracle Web Center批处理器会将这些映像摄取到oracle Web中心内容。下面的代码试图实现主要目标。
问题:
代码运行时间太长。目前要导出100000个blob并写入文件需要10.9,要导出10000需要0.5。
我已经在使用批量收集,优化器提示。如何改进此代码以实现更快的性能,以便能够将尽可能多的图像导出和写入平面文件?
请咨询
SET SERVEROUTPUT ON
CREATE OR REPLACE PACKAGE BODY OWCMIGRATION.biometric_blob_to_file_april28
AS
/*
-------------------------------------------------------------------------------------------------------------------------------------
Procedure Name: write_bio_blob_to_file_mar26
Procedure Description: This procedure is used to convert blob data into image file.
-------------------------------------------------------------------------------------------------------------------------------------
*/
PROCEDURE write_bio_blob_to_file_mar26( ls_pin_ref VARCHAR2, ls_msisdn VARCHAR2,l_blob BLOB, ls_file_name VARCHAR2)
AS
lclob_file CLOB;
ln_cursor_cnt NUMBER := 0;
t_blob BLOB;
l_file UTL_FILE.FILE_TYPE;
t_TotalSize NUMBER;
t_file_name VARCHAR2 (100);
t_remain NUMBER;
t_position NUMBER := 1;
l_buffer RAW(32760);--VARCHAR2(32760);--
l_amount BINARY_INTEGER := 32760;
err_code VARCHAR2(10);
err_msg VARCHAR2(250);
BEGIN
DBMS_LOB.createtemporary (lclob_file, TRUE);
--Incrementing the cursor count and the commit count for eacj record being processed.
ln_cursor_cnt := ln_cursor_cnt + 1;
--Calculationg length and getting file name of the image*/
SELECT DBMS_LOB.getlength (l_blob) BLOB_BASE64, ls_file_name
INTO t_TotalSize, t_file_name
FROM DUAL
WHERE nvl(length(dbms_lob.getlength(l_blob)),0)<>0;
--If length of blob is not null then inserting into image log table for generating config file*/
IF t_TotalSize <>0 THEN
INSERT /*+ APPEND PARALLEL */ INTO Image_Log3
VALUES(ls_pin_ref,ls_msisdn,ls_file_name);
COMMIT;
END IF;
--Opening File in Write mode in directory migration2
l_file := UTL_FILE.fopen ('ECM_MIGRATION_QA', t_file_name, 'wb', 32767); --BIO_MIGRATION_QA
t_remain := t_TotalSize;
--Converting Blob into Images
-- IF t_TotalSize < l_amount THEN
-- dbms_output.put_line('0 blob:'||ls_file_name);
--
-- dbms_output.put_line('length:'||t_TotalSize);
-- UTL_FILE.put_raw (l_file, l_buffer);
-- UTL_FILE.fflush (l_file);
-- ELSE
WHILE t_position < t_TotalSize
LOOP
BEGIN
dbms_output.put_line(' blob:'||ls_file_name);
DBMS_LOB.read (l_blob, l_amount, t_position, l_buffer);
UTL_FILE.put_raw (l_file, l_buffer);
UTL_FILE.fflush (l_file);
t_position := t_position + l_amount;
t_remain := t_remain - l_amount;
IF t_remain < 32767
THEN
l_amount := t_remain;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
END;
END LOOP;
-- END IF;
UTL_FILE.FCLOSE(l_file);
DBMS_LOB.FREETEMPORARY (lclob_file);
EXCEPTION
--Exception to handle Invalid Path
WHEN UTL_FILE.Invalid_path
THEN
DBMS_OUTPUT.put_line ('Invalid Dir');
DBMS_OUTPUT.put_line ('Directory Error: '||ls_file_name );
--Exception to handle Invalid Operation
WHEN UTL_FILE.Invalid_operation
THEN
DBMS_OUTPUT.put_line ('Invalid operation');
DBMS_OUTPUT.put_line ('File Error write_bio_blob_to_file: '||ls_file_name );
WHEN OTHERS
THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
DBMS_OUTPUT.put_line ('Others ');
DBMS_OUTPUT.put_line ('File Error others: '||ls_file_name );
INSERT /*+ APPEND PARALLEL */ INTO image_null_log2
VALUES(ls_pin_ref,ls_msisdn,ls_file_name,l_blob,err_code,err_msg);
COMMIT;
END write_bio_blob_to_file_mar26;
/*
-------------------------------------------------------------------------------------------------------------------------------------
Procedure Name: exp_bio_blob_to_file_mar26
Procedure Description : This Procedure is used to export images.
-------------------------------------------------------------------------------------------------------------------------------------
*/
PROCEDURE exp_bio_blob_to_file_mar26
AS
TYPE BioCurTyp IS REF CURSOR;
bio_cv BioCurTyp;
-- Table type that can hold information about owc_isl_data_test
TYPE BioList_tab IS TABLE OF CUSTOMER_BIOMETRIC%ROWTYPE;
BiometricInfo BioList_tab;
start_time number;
end_time number;
l_diff number;
BEGIN
--Truncating Image Log1 table
EXECUTE IMMEDIATE 'truncate table Image_Log3';
EXECUTE IMMEDIATE 'truncate table Image_null_log3';
start_time := DBMS_UTILITY.get_time;
--create a cursor that select all biometric data
OPEN bio_cv FOR
SELECT /*+ FIRST_ROWS*/ *
FROM CUSTOMER_BIOMETRIC
WHERE rownum<1000000;
--fetching biometric data from cursor in bulk of 1000
FETCH bio_cv BULK COLLECT INTO BiometricInfo LIMIT 700000;
CLOSE bio_cv;
/* Export images from owc_isl_data_test table then write correspoding image to directory
to MIGRATION_2 which I mapped to ojecmtst01 path /ecm/digital/migration */
FOR i IN BiometricInfo.FIRST .. BiometricInfo.LAST LOOP
write_bio_blob_to_file_mar26 (BiometricInfo(i).pinref,BiometricInfo(i).MSISDN,BiometricInfo(i).PHOTO_PERSON,BiometricInfo(i).MSISDN ||'_PT_05.jpg');
write_bio_blob_to_file_mar26 (BiometricInfo(i).pinref,BiometricInfo(i).MSISDN,BiometricInfo(i).FINGPRNT_LEFT_THUMB,BiometricInfo(i).MSISDN ||'_LT_05.wsq');
write_bio_blob_to_file_mar26 (BiometricInfo(i).pinref,BiometricInfo(i).MSISDN,BiometricInfo(i).FINGPRNT_LEFT_INDEX,BiometricInfo(i).MSISDN ||'_LF_05.wsq');
write_bio_blob_to_file_mar26 (BiometricInfo(i).pinref,BiometricInfo(i).MSISDN,BiometricInfo(i).FINGPRNT_RIGHT_THUMB,BiometricInfo(i).MSISDN ||'_RT_05.wsq');
write_bio_blob_to_file_mar26 (BiometricInfo(i).pinref,BiometricInfo(i).MSISDN,BiometricInfo(i).FINGPRNT_RIGHT_INDEX,BiometricInfo(i).MSISDN ||'_RF_05.wsq');
--write_bio_blob_to_file_mar26 (BiometricInfo(i).pin_ref,BiometricInfo(i).MSISDN,BiometricInfo(i).PASSPORT_PHOTO,BiometricInfo(i).msisdn||'_PP_05.jpg');
--write_bio_blob_to_file_mar26 (BiometricInfo(i).pin_ref,BiometricInfo(i).MSISDN,BiometricInfo(i).CER_IMG_DATA,BiometricInfo(i).msisdn||'_CI_05.jpg');
END LOOP;
COMMIT;
end_time := DBMS_UTILITY.get_time;
l_diff := (end_time-start_time)/100;
INSERT INTO time_log
VALUES(l_diff);
DBMS_OUTPUT.PUT_LINE('start time ' || to_char(start_time));
DBMS_OUTPUT.PUT_LINE('end time ' || to_char(end_time));
DBMS_OUTPUT.PUT_LINE('Elapsed time ' || l_diff ||'sec');
DBMS_OUTPUT.put_line('end loop');
EXCEPTION
--Exception to handle Invalid Path
WHEN UTL_FILE.Invalid_path
THEN
DBMS_OUTPUT.put_line('Invalid Dir');
--Exception to handle Invalid Operation
WHEN UTL_FILE.Invalid_operation
THEN
DBMS_OUTPUT.put_line('Invalid operation');
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Others '||SQLCODE||SUBSTR(SQLERRM, 1, 200));
END exp_bio_blob_to_file_mar26;
End biometric_blob_to_file_april28;
/
回答Ben的问题
我不确定什么是最好的平行方式。我尝试了并行性,因为将记录分成10万个范围,但无法使其正常工作。我做了以下
在同一个包中,我创建了名为exp_bio_blob_to_file_1_mar26的过程。此过程类似于exp_bio_blob_to_file_mar26,但以下SQL
除外 - 选择100 001到200000之间的记录 /
打开bio_cv FOR
选择MSISDN,
PINREF,
PHOTO_PERSON,
FINGPRNT_LEFT_THUMB,
FINGPRNT_LEFT_INDEX,
FINGPRNT_RIGHT_THUMB,
FINGPRNT_RIGHT_INDEX
FROM(选择a。,ROWNUM rnum
FROM(SELECT / + FIRST_ROWS / *
来自CUSTOMER_BIOMETRIC)a
- 选择范围内记录的结束点
REREUM&lt; = 200000)
- 选择范围内记录的起始点
在哪里rnum&gt; = 100001;
在
上设置serveroutputDECLARE jobnumber33号码; jobnumber44号码;
start_time号码; end_time号码; l_diff号码; 开始 start_time:= DBMS_UTILITY.get_time; dbms_job.submit(jobnumber33,'begin biometric_blob_to_file_mar28.exp_bio_blob_to_file_mar26; dbms_output.put_line(''test1''); end;'); 承诺; dbms_job.submit(jobnumber44,'begin biometric_blob_to_file_mar28.exp_bio_blob_to_file_1_mar26; dbms_output.put_line(''test2''); end;'); 承诺; dbms_job.run(jobnumber33); DBMS_OUTPUT.PUT_LINE('已提交作业'|| jobnumber33);
dbms_job.run(jobnumber44); DBMS_OUTPUT.PUT_LINE('提交的作业'|| jobnumber44);
end_time:= DBMS_UTILITY.get_time; l_diff:=(end_time-start_time)/ 100; DBMS_OUTPUT.PUT_LINE('经过时间'|| l_diff ||'秒');
END; /
第一份工作将被执行罚款,但第二份工作将直接进入“其他”部分而不执行。我不知道为什么..我正在尝试创建2个不同的表,每个表都包含要导出的单独记录范围。
回答杰弗里的问题
我刚刚获得了下面的磁盘io统计信息。我看起来像磁盘io不是瓶颈
root@owcm880 # zpool iostat owcmigration 3
capacity operations bandwidth
pool alloc free read write read write
------------ ----- ----- ----- ----- ----- -----
owcmigration 6.20G 289G 0 5 393 140K
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 65 0 881K
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0
owcmigration 6.20G 289G 0 0 0 0