【发布时间】:2018-08-17 00:15:51
【问题描述】:
我正在使用 Oracle 11g Express Edition (XE) 和 SQL Developer。我编写了以下存储过程作为概念证明,将多个 BLOB 写入我的 image_dir(C:\TEMP)。它工作正常。我想知道这是否是将大规模(10 亿张图像)的 blob 写入目录的正确方法?你有什么经验吗?多少张图片花了多长时间?
create or replace PROCEDURE write_blob_to_file_Dcloud_v1
AS
v_lob_image_name VARCHAR (100);
v_lob_image_id NUMBER;
v_blob BLOB;
v_buffer RAW (32767);
v_buffer_size BINARY_INTEGER;
v_amount BINARY_INTEGER;
v_offset NUMBER (38) := 1;
v_chunksize INTEGER;
v_out_file UTL_FILE.file_type;
BEGIN
-- +-------------------------------------------------------------------------+
-- | SELECT THE BLOBS FROM THE DATABASE TABLE |
-- +-------------------------------------------------------------------------+
FOR i IN (SELECT
employee_id v_lob_image_id,
(first_name || ' ' || last_name) AS v_lob_image_name,
DBMS_LOB.GETLENGTH(v_blob) v_len,
employee_picture v_blob
FROM HR.employees)
LOOP
-- +-------------------------------------------------------------------------------------+
-- | FIND OUT THE CHUNKSIZE FOR THIS BLOB COLUMN. |
-- | BUFFERSIZE IS USED TO PARSE CHUNKS OF DATA/BYTES FROM THE IMAGE. |
-- | IF NOT SPECIFIED, THE SYSTEM LEVEL MODULE WOULD READ MUCH SMALLER CHUNKS AT A TIME, |
-- | AND EACH READ AND WRITE IS AN EXPENSIVE OPERATION. SO IT IS BEST TO READ IN CHUNKS. |
-- | THE PURPOSE OF THE OUTER LOOP IS TO LOOP THRU ALL THE BLOBS IN THE TABLE. THE CODE |
-- | WILL NEED TO READ THE IMAGE FROM THE BEGINNING SO INITIALIZING THE V_OFFSET TO 1, |
-- | TAKE CARE OF THAT. |
-- +-------------------------------------------------------------------------------------+
v_offset := 1;
v_chunksize := DBMS_LOB.getchunksize (i.v_blob);
IF (v_chunksize < 32767)
THEN
v_buffer_size := v_chunksize;
ELSE
v_buffer_size := 32767;
END IF;
v_amount := v_buffer_size;
-- +---------------------------------------------------------------------------------------+
-- |OPEN THE BLOB. TO PREVENT NOT YET CLOSE OR ALREADY OPENED BLOBS, USE THE FOLLOWING CODE|
-- +---------------------------------------------------------------------------------------+
IF (dbms_lob.isopen(i.v_blob) = 0)
THEN
dbms_lob.open(i.v_blob,dbms_lob.lob_readonly);
END IF;
-- +---------------------------------------------------------------------------------------+
-- | WRITE CONTENTS OF THE BLOB TO A FILE |
-- +---------------------------------------------------------------------------------------+
v_out_file :=
UTL_FILE.fopen (
location => 'IMAGE_DIR',
filename => ( ''
|| i.v_lob_image_id
|| '_'
|| i.v_lob_image_name
|| '.JPG'),
open_mode => 'wb',
max_linesize => 32767);
-- +---------------------------------------------------------------------------------------+
-- |THIS INNER LOOP (WHILE LOOP) IS TO TAKE EACH BLOB AND PROCESS IT. V_AMOUNT IS SET TO |
-- |BUFFERSIZE. BUFFERSIZE IS USED TO PARSE CHUNKS OF DATA/BYTES FROM IMAGE. IT LOOPS THRU |
-- | UNTIL IT READS ALL THE CHUNKS OF AN IMAGE (READ THE ENTIRE IMAGE). |
-- +---------------------------------------------------------------------------------------+
WHILE v_amount >= v_buffer_size
LOOP
DBMS_LOB.read (i.v_blob,
v_amount,
v_offset,
v_buffer);
v_offset := v_offset + v_amount;
UTL_FILE.put_raw (v_out_file, v_buffer, TRUE);
UTL_FILE.fflush (v_out_file);
END LOOP;
UTL_FILE.fflush (v_out_file);
UTL_FILE.fclose (v_out_file);
-- +---------------------------------------------------------------------------------------+
-- |CLOSE THE BLOB. TO PREVENT NOT YET CLOSE OR ALREADY OPENED BLOBS, USE THE FOLLOWING CODE|
-- +---------------------------------------------------------------------------------------+
IF ( dbms_lob.isopen(i.v_blob) = 1 )
THEN
dbms_lob.close(i.v_blob);
END IF;
END LOOP;
END;
【问题讨论】:
-
Oracle 11g Express Edition 有 11 GB 的限制,如何才能拥有 10 亿张图像。这意味着您的 BLOB 的平均大小仅为 10 字节。
-
@WernfriedDomscheit。我的意思是说 Oracle 的任何企业版,而不是 Oracle 11g(XE)。我只是想听听人们在将大量 blob 写入目录时的经验。感谢您的回复。
-
10 亿张图像意味着数 TB 的数据。我怀疑你在 c:/Temp 上有这个空间你期望什么时间,即你的要求是什么?您无法在几秒钟或几分钟内写入如此多的数据。
-
你是对的。想法是连接到 AWS Snowball,而不是文件系统上的目录。最终目标是将 TB 图像从 Oracle DB 中取出并放入 AWS S3。
标签: sql oracle stored-procedures plsql oracle11g