【问题标题】:The right way to write large number of blobs to a directory将大量 blob 写入目录的正确方法
【发布时间】: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 字节。
  • 这里是它指定限制的链接:oracle.com/technetwork/database/database-technologies/…
  • @WernfriedDomscheit。我的意思是说 Oracle 的任何企业版,而不是 Oracle 11g(XE)。我只是想听听人们在将大量 blob 写入目录时的经验。感谢您的回复。
  • 10 亿张图像意味着数 TB 的数据。我怀疑你在 c:/Temp 上有这个空间你期望什么时间,即你的要求是什么?您无法在几秒钟或几分钟内写入如此多的数据。
  • 你是对的。想法是连接到 AWS Snowball,而不是文件系统上的目录。最终目标是将 TB 图像从 Oracle DB 中取出并放入 AWS S3。

标签: sql oracle stored-procedures plsql oracle11g


【解决方案1】:

回答:

我想知道这是否是大规模编写 blob 的正确方法

当然。恰当的。随便。

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

永远不要两种方式

所以,我相信您关于发布代码的功效的问题是一个转移注意力的问题。你已经知道这很好。没有银弹。

您是在问一个架构问题,但没有详细解释需求是什么——这是纯粹的推测性意见征集。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 2017-06-29
    • 2014-01-15
    • 2019-11-27
    • 2011-09-03
    • 1970-01-01
    相关资源
    最近更新 更多