将大量blob写入目录的正确方法

时间:2018-03-08 15:20:45

标签: sql oracle stored-procedures plsql oracle11g

我正在使用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;

1 个答案:

答案 0 :(得分:1)

回答:

  

我想知道这是否是一种以非常大的规模编写blob的正确方法

不确定。正确。不管。

我认为具有十亿个图像的应用程序的任何架构设计都将决定这些将存储在数据库中(作为BLOB)还是作为对文件系统的引用(作为BFILE )。

从不 BOTH 方式。

所以,我相信你关于你发布的代码的功效的问题是一个红色的鲱鱼。你已经知道它很好。没有银子弹。

你问的是一个建筑问题而没有详细解释这些要求是什么 - 这是对纯粹投机性观点的征求。