我正在使用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;
答案 0 :(得分:1)
回答:
我想知道这是否是一种以非常大的规模编写blob的正确方法
不确定。正确。不管。
我认为具有十亿个图像的应用程序的任何架构设计都将决定这些将存储在数据库中(作为BLOB
)还是作为对文件系统的引用(作为BFILE
)。
从不 BOTH 方式。
所以,我相信你关于你发布的代码的功效的问题是一个红色的鲱鱼。你已经知道它很好。没有银子弹。
你问的是一个建筑问题而没有详细解释这些要求是什么 - 这是对纯粹投机性观点的征求。