Call now: 252-767-6166  
Oracle Training Oracle Support Development Oracle Apps

 
 Home
 E-mail Us
 Oracle Articles
New Oracle Articles


 Oracle Training
 Oracle Tips

 Oracle Forum
 Class Catalog


 Remote DBA
 Oracle Tuning
 Emergency 911
 RAC Support
 Apps Support
 Analysis
 Design
 Implementation
 Oracle Support


 SQL Tuning
 Security

 Oracle UNIX
 Oracle Linux
 Monitoring
 Remote s
upport
 Remote plans
 Remote
services
 Application Server

 Applications
 Oracle Forms
 Oracle Portal
 App Upgrades
 SQL Server
 Oracle Concepts
 Software Support

 Remote S
upport  
 Development  

 Implementation


 Consulting Staff
 Consulting Prices
 Help Wanted!

 


 Oracle Posters
 Oracle Books

 Oracle Scripts
 Ion
 Excel-DB  

Don Burleson Blog 


 

 

 


 

 

 
 


How to export/unload a BLOB/CLOB

Oracle Database Tips by Donald BurlesonNovember 19, 2015

How to export/unload an Oracle BLOB large object

By Laurent Schneider

This article describes how to export and unload a large object (BLOB, CLOB) from a database table into a flat file.

There is more than one post on how to unload blob from the database, mostly in PL/SQL with utl_file.put_raw and with Java with FileOutputStream.

Unfortunately both ways of exporting a LOB are slow due to the 32k limitation of put_raw in utl_file and due to a low "optimum buffer size" retrieved by myBlob.getBufferSize(), I increased the java stream buffer to 20M or to the size of the lob, whichever is smaller.

Using Java to export a BLOB/CLOB

Using java for exporting a blob (read large binary large object) is about 3x faster than using PL/SQL in my test.
 
SQL> CREATE USER USER1 IDENTIFIED BY SeCrEt;
SQL> GRANT CREATE SESSION , CREATE PROCEDURE TO USER1;
SQL> connect user1/SeCrEt
SQL> CREATE OR REPLACE JAVA SOURCE NAMED "BlobHandler"
  2     AS import java.lang.*;
  3  import java.sql.*;
  4  import oracle.sql.*;
  5  import java.io.*;
  6  public class BlobHandler {
  7    public static void ExportBlob(String myFile, BLOB myBlob) throws Exception {
  8      File binaryFile = new File(myFile);
  9      FileOutputStream outStream = new FileOutputStream(binaryFile);
10      InputStream inStream = myBlob.getBinaryStream();
11      int size;
12      if (myBlob.length()> 20000000) {  // tune this to whatever appropriate value
13        size = 20000000;
14      } else {
15        size = (int)myBlob.length();
16      }
17      byte[] buffer = new byte[size];
18      int length = -1;
19      while ((length = inStream.read(buffer)) != -1)
20      {
21        outStream.write(buffer, 0, length);
22        outStream.flush();
23      }
24      inStream.close();
25      outStream.close();
26    }
27  }
28  /
SQL> ALTER JAVA SOURCE "BlobHandler" COMPILE;
SQL> sho error
No errors.
SQL> CREATE OR REPLACE PROCEDURE ExportBlobJava (p_file   IN VARCHAR2,
  2                                              p_blob   IN BLOB)
  3  AS
  4     LANGUAGE JAVA
  5     NAME 'BlobHandler.ExportBlob(java.lang.String, oracle.sql.BLOB)';
  6  /
SQL> connect / as sysdba
SQL> EXEC Dbms_Java.Grant_Permission( 'USER1', 'SYS:java.io.FilePermission','/tmp/javatest', 'write' )

 
Next, we start unloading the CLOB/BLOB:
 
SQL> connect user1/SeCrEt
SQL> CREATE OR REPLACE PROCEDURE ExportBlobPlsql (p_dir    IN VARCHAR2,
  2                                               p_file   IN VARCHAR2,
  3                                               p_blob   IN BLOB)
  4  AS
  5     blob_length     INTEGER;
  6     out_file        UTL_FILE.FILE_TYPE;
  7     v_buffer        RAW (32767);
  8     chunk_size      BINARY_INTEGER := 32767;
  9     blob_position   INTEGER := 1;
10  BEGIN
11     blob_length := DBMS_LOB.GETLENGTH (p_blob);
12     out_file :=
13        UTL_FILE.FOPEN (p_dir,
14                        p_file,
15                        'wb',
16                        chunk_size);
17     WHILE blob_position <= blob_length
18     LOOP
19        IF blob_position + chunk_size - 1 > blob_length
20        THEN
21           chunk_size := blob_length - blob_position + 1;
22        END IF;
23
24        DBMS_LOB.READ (p_blob,
25                       chunk_size,
26                       blob_position,
27                       v_buffer);
28        UTL_FILE.PUT_RAW (out_file, v_buffer, TRUE);
29        blob_position := blob_position + chunk_size;
30     END LOOP;
31     UTL_FILE.FCLOSE (out_file);
32  END;
33  /
SQL> connect / as sysdba
SQL> CREATE OR REPLACE DIRECTORY tmp AS '/tmp';
SQL> grant write on directory tmp to user1;


Here again, I give write access to one directory:
 
SQL> connect user1/SeCrEt
SQL> VAR c BLOB
SQL> exec :c := UTL_RAW.cast_to_raw ('X'); FOR i IN 1 .. 15 LOOP  DBMS_LOB.append (:C, :C); END LOOP
SQL> SELECT DBMS_LOB.getlength (:c)/1024 KB FROM DUAL;


I have created a 32K BLOB variable, and I am doubling its size each time to see how it scales
 
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024 KB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024 KB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024 KB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024 KB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)

 
For small files, we do not see much of a difference between the export speed using Java and PL/SQL. This is because the 32k buffer of PL/SQL is acceptable for small files.

Below, I run ExportBlobJava to unload the CLOB/BLOB from Oracle:
 
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)
SQL> exec DBMS_LOB.append (:C, :C)
SQL> SELECT DBMS_LOB.getlength (:c)/1024/1024 MB FROM DUAL;
SQL> EXEC ExportBlobJava('/u99/backup/sw/tmp/javatest',:c)
SQL> EXEC ExportBlobPlsql('TMP','/plsqltest',:c)

 

 
Get the Complete
Oracle SQL Tuning Information 

The landmark book "Advanced Oracle SQL Tuning  The Definitive Reference"  is filled with valuable information on Oracle SQL Tuning. This book includes scripts and tools to hypercharge Oracle 11g performance and you can buy it for 30% off directly from the publisher.

 

 

Burleson is the American Team

Note: This Oracle documentation was created as a support and Oracle training reference for use by our DBA performance tuning consulting professionals.  Feel free to ask questions on our Oracle forum.

Verify experience! Anyone considering using the services of an Oracle support expert should independently investigate their credentials and experience, and not rely on advertisements and self-proclaimed expertise. All legitimate Oracle experts publish their Oracle qualifications.

Errata?  Oracle technology is changing and we strive to update our BC Oracle support information.  If you find an error or have a suggestion for improving our content, we would appreciate your feedback.  Just  e-mail:  

and include the URL for the page.


                    









Burleson Consulting

The Oracle of Database Support

Oracle Performance Tuning

Remote DBA Services


 

Copyright © 1996 -  2020

All rights reserved by Burleson

Oracle ® is the registered trademark of Oracle Corporation.

 

 

��  
 
 
Oracle Training at Sea
 
 
 
 
oracle dba poster
 

 
Follow us on Twitter 
 
Oracle performance tuning software 
 
Oracle Linux poster