【发布时间】:2013-05-31 04:13:35
【问题描述】:
我需要从我们的 Oracle 11g (11.2.0.3) 系统导出 BLOB。该过程非常适合小于 32,767 字节的 BLOB(JPG 照片)。我可以使用 dbms_log.read 和 utl_file.put_raw 在 5 秒内将约 4000 张照片导出到数据库服务器上的本地目录。如果文件超过了读取缓冲区的 32,767 字节限制,这就是性能问题的开始。我看过关于确切性能问题的类似帖子,但提供的解决方案已经过研究但没有成功。根据监控工具,CPU、I/O 和内存在导出期间没有受到压力。我试图理解为什么与 32,767 字节以下的 BLOB 相比,必须以 32,767 字节增量拼凑在一起的较大 BLOB(所有这些 BLOB 的大小都低于 100K)具有如此巨大的导出速度。导出大型 BLOB 时,每个文件最多可能需要 15 秒才能导出。
Related Post of slow blob extraction
Related Post of BLOB export tuning
是否有人遇到过文件大于 32,767 字节的 BLOB 导出缓慢的情况?
DECLARE
CURSOR cur_photo IS
select substr(c.custnum, -7, length(c.custnum)) custnum,
cp.cust_id,
cp.photo
from customer c
inner join customer_photo cp
on c.cust_id = cp.cust_id
inner join customer_def_grp_value cdv
on c.cust_id = cdv.cust_id;
select_sql varchar2(225);
l_file UTL_FILE.FILE_TYPE;
l_buffer RAW(32767);
l_amount PLS_INTEGER := 32767;
l_pos PLS_INTEGER := 1;
l_blob BLOB;
l_blob_len PLS_INTEGER;
l_filename varchar2(225);
error_number varchar2(225);
error_message varchar2(225);
BEGIN
--dbms_output.put_line('Starting at: ' || to_char(systimestamp, 'DD-MON-YYYY HH:MI:SS.FF6'));
--DBMS_OUTPUT.ENABLE (buffer_size => NULL);
FOR custphoto IN cur_photo LOOP
--dbms_output.put_line('In the loop ' || custphoto.cust_id);
select_sql := 'SELECT photo FROM customer_photo WHERE cust_id = :cust_id';
--dbms_output.put_line('Statement: ' || select_sql);
EXECUTE IMMEDIATE select_sql INTO l_blob using custphoto.cust_id;
l_blob_len := DBMS_LOB.getlength(l_blob);
--dbms_output.put_line('BLOB length: ' || l_blob_len);
-- Set the filename
l_filename := custphoto.custnum || '.jpg';
--dbms_output.put_line('Filename: ' || l_filename);
-- Open the destination file.
l_file := UTL_FILE.fopen('jpeg', l_filename, 'wb', 32767);
--dbms_output.put_line('Start Export at: ' || to_char(systimestamp, 'DD-MON-YYYY HH:MI:SS.FF6'));
IF l_blob_len < 32767 then
--dbms_output.put_line('BLOB < 32767 bytes');
DBMS_LOB.read(l_blob, l_blob_len, l_pos, l_buffer);
UTL_FILE.put_raw(l_file, l_buffer, TRUE);
ELSE -- write in pieces
--dbms_output.put_line('BLOB >= 32767 bytes');
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer);
UTL_FILE.put_raw(l_file, l_buffer, TRUE);
l_pos := l_pos + l_amount;
END LOOP;
END IF;
-- Close the file.
UTL_FILE.fclose(l_file);
-- Reset the pos for the next jpg file
l_pos := 1;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
-- Close the file if something goes wrong.
error_number := sqlcode;
error_message := substr(sqlerrm, 1, 100);
dbms_output.put_line('Error Number: ' || error_number);
dbms_output.put_line('Error Message: ' || error_message);
utl_file.fclose_all;
RAISE;
END;
提前感谢您对 BLOB 导出的任何见解。
【问题讨论】:
-
速度慢的原因是 WHILE 子句中的 dbms_lob.read 调用。
标签: performance oracle11g export blob utl-file