Oracle

從表中導出大量文件

  • January 2, 2018

我正在使用 Oracle Database 11g 版本 11.1.0.6.0 並且有一個表記錄大量帶有 ID (ID) 的文件 (GIF)。

 Name                                      Type
 ----------------------------------------- ----------------------------
 ID                                        VARCHAR2(50)
 GIF                                       BLOB

目前我正在使用這段程式碼來導出圖片:

DECLARE
 l_file      UTL_FILE.FILE_TYPE;
 l_name      VARCHAR2(50);
 l_buffer    RAW(32767);
 l_amount    BINARY_INTEGER := 32767;
 l_pos       INTEGER := 1;
 l_count     INTEGER := 1;
 l_blob_len  INTEGER;
BEGIN
 for x in (SELECT * FROM MY_TABLE) loop
       l_blob_len := DBMS_LOB.getlength(x.GIF);
       l_file := UTL_FILE.fopen('BLOBS',x.ID||'-'||l_count||'.gif','wb', 32767);
       l_pos := 1;
       WHILE l_pos < l_blob_len LOOP
           DBMS_LOB.read(x.GIF, l_amount, l_pos, l_buffer);
           UTL_FILE.put_raw(l_file, l_buffer, TRUE);
           l_pos := l_pos + l_amount;
       END LOOP;
       UTL_FILE.fclose(l_file);
       l_count := l_count + 1;
 end loop;

EXCEPTION
 WHEN OTHERS THEN
   IF UTL_FILE.is_open(l_file) THEN
     UTL_FILE.fclose(l_file);
   END IF;
   RAISE;
END;
/

這段程式碼執行良好,**但問題是,表中有大約 1 億行。**在我的電腦上,導出速度大約只有 7 張圖片/秒。

那麼,有沒有什麼方法可以加速導出呢?謝謝!

您可以使用ORA_HASH函式將表數據拆分為不同的組。查看修改後的 SELECT-FROM-MY_TABLE 子句。在三個不同的 sqlplus 會話中執行此腳本並測量每秒提取的文件數。

腳本 0:

DECLARE
 l_file      UTL_FILE.FILE_TYPE;
 l_name      VARCHAR2(50);
 l_buffer    RAW(32767);
 l_amount    BINARY_INTEGER := 32767;
 l_pos       INTEGER := 1;
 l_count     INTEGER := 1;
 l_blob_len  INTEGER;
BEGIN
 for x in (SELECT * FROM MY_TABLE where ora_hash(rowid,2,123)=0) loop
       l_blob_len := DBMS_LOB.getlength(x.GIF);
       l_file := UTL_FILE.fopen('BLOBS',x.ID||'-'||l_count||'.gif','wb', 32767);
       l_pos := 1;
       WHILE l_pos < l_blob_len LOOP
           DBMS_LOB.read(x.GIF, l_amount, l_pos, l_buffer);
           UTL_FILE.put_raw(l_file, l_buffer, TRUE);
           l_pos := l_pos + l_amount;
       END LOOP;
       UTL_FILE.fclose(l_file);
       l_count := l_count + 1;
 end loop;

EXCEPTION
 WHEN OTHERS THEN
   IF UTL_FILE.is_open(l_file) THEN
     UTL_FILE.fclose(l_file);
   END IF;
   RAISE;
END;
/

腳本1:

DECLARE
 l_file      UTL_FILE.FILE_TYPE;
 l_name      VARCHAR2(50);
 l_buffer    RAW(32767);
 l_amount    BINARY_INTEGER := 32767;
 l_pos       INTEGER := 1;
 l_count     INTEGER := 1;
 l_blob_len  INTEGER;
BEGIN
 for x in (SELECT * FROM MY_TABLE where ora_hash(rowid,2,123)=1) loop
       l_blob_len := DBMS_LOB.getlength(x.GIF);
       l_file := UTL_FILE.fopen('BLOBS',x.ID||'-'||l_count||'.gif','wb', 32767);
       l_pos := 1;
       WHILE l_pos < l_blob_len LOOP
           DBMS_LOB.read(x.GIF, l_amount, l_pos, l_buffer);
           UTL_FILE.put_raw(l_file, l_buffer, TRUE);
           l_pos := l_pos + l_amount;
       END LOOP;
       UTL_FILE.fclose(l_file);
       l_count := l_count + 1;
 end loop;

EXCEPTION
 WHEN OTHERS THEN
   IF UTL_FILE.is_open(l_file) THEN
     UTL_FILE.fclose(l_file);
   END IF;
   RAISE;
END;
/

腳本 2:

DECLARE
 l_file      UTL_FILE.FILE_TYPE;
 l_name      VARCHAR2(50);
 l_buffer    RAW(32767);
 l_amount    BINARY_INTEGER := 32767;
 l_pos       INTEGER := 1;
 l_count     INTEGER := 1;
 l_blob_len  INTEGER;
BEGIN
 for x in (SELECT * FROM MY_TABLE where ora_hash(rowid,2,123)=2) loop
       l_blob_len := DBMS_LOB.getlength(x.GIF);
       l_file := UTL_FILE.fopen('BLOBS',x.ID||'-'||l_count||'.gif','wb', 32767);
       l_pos := 1;
       WHILE l_pos < l_blob_len LOOP
           DBMS_LOB.read(x.GIF, l_amount, l_pos, l_buffer);
           UTL_FILE.put_raw(l_file, l_buffer, TRUE);
           l_pos := l_pos + l_amount;
       END LOOP;
       UTL_FILE.fclose(l_file);
       l_count := l_count + 1;
 end loop;

EXCEPTION
 WHEN OTHERS THEN
   IF UTL_FILE.is_open(l_file) THEN
     UTL_FILE.fclose(l_file);
   END IF;
   RAISE;
END;
/

如果這可行,您可以嘗試生成並啟動更多腳本。

引用自:https://dba.stackexchange.com/questions/194338