Read Blob from database and write to a local file
i needed a method to test the throughput of a system when working with blob data. A lot of finger pointing occurred at the application middleware, but i was concerned the underlying database, network and/or SAN architecture was at fault. Hence writing a simple db resident script to do the work of the middleware whose main content fields have Blob/clob definitions.
Steps
- Define the Stored Procedures
- Create a table
- Connect a client – if applicable, run this locally on the db server to remove any client network latency.
create stored procedure
CREATE OR REPLACE PROCEDURE kate.WriteBLOBToFILE (itemId IN NUMBER,v_dir varchar2,runno IN number) IS v_blob BLOB; blob_length INTEGER; out_file UTL_FILE.FILE_TYPE; v_buffer RAW(32767); chunk_size BINARY_INTEGER := 32767; blob_position INTEGER := 1; BEGIN -- Retrieve the BLOB for reading --SELECT item_data INTO v_blob FROM pritemdata WHERE data_id = (select ContId; SELECT item_data INTO v_blob FROM pritemdata WHERE data_id in (select data_id from prdatareference where item_id=itemId and data_type=1); -- Retrieve the SIZE of the BLOB blob_length:=DBMS_LOB.GETLENGTH(v_blob); -- Open a handle to the location to write the BLOB to file out_file := UTL_FILE.FOPEN (v_dir,itemId||'_'||runno , 'wb', chunk_size); -- Write the BLOB to file in chunks WHILE blob_position <= blob_length LOOP IF blob_position + chunk_size - 1 > blob_length THEN chunk_size := blob_length - blob_position + 1; END IF; DBMS_LOB.READ(v_blob, chunk_size, blob_position, v_buffer); UTL_FILE.PUT_RAW(out_file, v_buffer, TRUE); blob_position := blob_position + chunk_size; END LOOP; -- Close the file handle UTL_FILE.FCLOSE (out_file); END;
Write lob into database
1. Create table
CREATE TABLE BLOB_DATA ( ID NUMBER, BLOB_DATA BLOB, PRTIME TIMESTAMP(6) DEFAULT SYSTIMESTAMP )
2. Create Stored Procedure
requirements – grant execute on dbms_lock;
CREATE OR REPLACE PROCEDURE AESUSER.insertBLOB (src_dir VARCHAR2,src_filename IN VARCHAR2,runno IN NUMBER,sleepinterval IN NUMBER) IS --exec insertBLOB3('DUMPDIR','test.jpg',5,1); bfile_offset NUMBER ; blob_offset NUMBER; v_file_loc BFILE; v_srcfile BLOB; v_srcfile_size INTEGER; lob_fileexists BOOLEAN := FALSE; BEGIN DBMS_OUTPUT.ENABLE(100000); v_file_loc := BFILENAME(src_dir,src_filename); lob_fileexists := DBMS_LOB.FILEEXISTS(v_file_loc) = 1; IF lob_fileexists THEN v_srcfile_size := DBMS_LOB.GETLENGTH(v_file_loc); DBMS_OUTPUT.PUT_LINE(src_dir|| '\' ||src_filename); DBMS_OUTPUT.PUT_LINE('FILE SIZE: ' || v_srcfile_size); DBMS_OUTPUT.PUT_LINE('Repetitions: ' || runno); DBMS_OUTPUT.PUT_LINE('Sleep INTERVAL: ' || sleepinterval); for i in 1..runno loop bfile_offset :=1; blob_offset :=1; INSERT INTO blob_data VALUES (i,EMPTY_BLOB(),systimestamp) returning blob_data into v_srcfile; dbms_lob.fileopen(v_file_loc, dbms_lob.file_readonly); dbms_lob.OPEN( v_srcfile, dbms_lob.lob_readwrite); DBMS_LOB.LOADBLOBFROMFILE ( dest_lob => v_srcfile, src_bfile => v_file_loc, amount => dbms_lob.lobmaxsize, dest_offset => bfile_offset, src_offset => blob_offset); dbms_lob.close(v_srcfile); dbms_lob.fileclose(v_file_loc); dbms_lock.sleep(sleepinterval); commit; end loop; ELSE DBMS_OUTPUT.PUT_LINE('ERROR. Supplied FILE Name '||src_dir|| '\' ||src_filename|| ' Does NOT exist'); END IF; EXCEPTION WHEN OTHERS THEN dbms_output.put_line('Error:' || SQLERRM); dbms_lob.close(v_srcfile); dbms_lob.fileclose(v_file_loc); END; /
3. Run Script.
sql> insertblob [oracle_directory],[filename],reptitions,interval);
- oracle_directory – name of directory within the database
- Filename – name of test file to import
- repetitions – qty of times to repeat test
- interval – sleep time between each repetition
remember to set serveroutput on if you wish a report at run end.
SQL> SET serveroutput ON
Success
SQL> EXEC insertBLOB('DUMPDIR','test.jpg',1,0); DUMPDIR\test.jpg FILE SIZE: 4637515 Repetitions: 1 Sleep INTERVAL: 0
failure
SQL> EXEC insertBLOB('DUMPDIR','testxxxxxx.jpg',1,0); ERROR. Supplied FILE DUMPDIR\testxxxxxx.jpg Does NOT existRead Lob FROM DATABASE