Slow Oracle BLOB upload with C# .NET and how to speed up.

In our current development we had the problem that our document upload into the oracle database took very long. It was completly beyond the pale.

With our Oracle Specialist Carl Reitschuster we discovered that this must be a problem of the ADO .NET implementation of Oracle. The upload with the PL Developer took only about 2 seconds, but with our C# code it took 46 seconds for the same document upload.

We found out that the ADO .NET Driver for Oracle is very slow when the upload buffer is set at once.


/// <summary>
/// Examples the of slow upload. (about 46 seconds)
/// </summary>
public void ExampleOfSlowUpload ()
{
    startTime = DateTime.Now;
    transaction = oracle.BeginTransaction();
    OracleCommand  command  = new OracleCommand (uploadSQL, oracle);
    OracleParameter uploadParameter = new OracleParameter(":blob", OracleDbType.Blob, ParameterDirection.Input);
    uploadParameter.Value = uploadBuffer;
 
    command.Parameters.Add(uploadParameter);
    command.ExecuteNonQuery();
    transaction.Commit();
 
    Console.WriteLine("Slow upload took : " + new TimeSpan(DateTime.Now.Ticks - startTime.Ticks).TotalSeconds + " seconds");
}

After a long term of search we discovered a solution that splits the upload buffer to small chunks. With this hint we could speed up the upload from 46 seconds to 4 seconds at all.


/// <summary>
/// Examples the of fast upload. (about 4 seconds)
/// </summary>
public void ExampleOfFastUpload ()
{
    startTime = DateTime.Now;
    transaction = oracle.BeginTransaction();
    OracleCommand  command  = new OracleCommand (uploadSQL, oracle);
    OracleParameter uploadParameter = new OracleParameter(":blob", OracleDbType.Blob, ParameterDirection.Input);
    OracleBlob blob = new OracleBlob(oracle);   
 
    int startOffset = 0;           
    int writeBytes = 0;
 
    /*
    * ... now load the buffer in small chunks to Oracle
    */
    blob.BeginChunkWrite();
    do
    {
        writeBytes = startOffset+BUFFER_SIZE>uploadBuffer.Length? uploadBuffer.Length-startOffset : BUFFER_SIZE;
        blob.Write(uploadBuffer, startOffset, writeBytes);
        startOffset += writeBytes;
    } while (startOffset < uploadBuffer.Length);
    blob.EndChunkWrite();
 
    uploadParameter.Value = blob;
 
    command.Parameters.Add(uploadParameter);
    command.ExecuteNonQuery();
    transaction.Commit();
 
    Console.WriteLine("Fast upload took : " + new TimeSpan(DateTime.Now.Ticks - startTime.Ticks).TotalSeconds + " seconds");
}

The complete demo solution can be downloaded from here:
OracleUploadProblem.zip

10 Responses to “Slow Oracle BLOB upload with C# .NET and how to speed up.”

  1. AJ’s blog » Blog Archive » Is memory shuffling the culprit? Says:

    [...] It was just a guess, yet Gerhard proved that it actually did solve the problem. If you are interested in the Oracle specifics I recommend reading Gerhards post… . [...]

  2. Joe Says:

    Could you please post the PL/SQL SP that you used for this test? I am trying to do this too but am getting an error and unsure how i have to change the script. thanks.

  3. Gerhard Stephan Says:

    Hi Joe –

    I’m not sure what you want me to post. It’s a C# problem and I don’t have any PL SQL Scripts for it. Are you looking for the DDL file?

    Which error do you get?

    Cheers
    Gerhard

  4. Andrew Harvey Says:

    I just tried this with Visual Studio 2005 and v1.0.3705 of the Oracle.Access.dll with the following results

    Slow upload took : 2.25 seconds
    Fast upload took : 5.078125 seconds

    I guess the slow upload problem is fixed in the latest version

    cheers
    Andrew

  5. Andrew Harvey Says:

    That should read the Oracle.DataAccess.dll

  6. Gerhard Stephan Says:

    Hi Andrew,

    I re-tested my piece of code. But the results are the same:

    Slow upload took : 35,453125 seconds
    Fast upload took : 3,359375 seconds

    I’m using Oracle DLL Version 1.102.2.20.

    I would recommend you to install the latest Oracle Driver which can be downloaded from: http://www.oracle.com/technology/software/tech/windows/odpnet/utilsoft.html

    It’s also important that you use the version that is compiled for VS 2005. Oracle delivers both versions within that distribution. So you have to choose the right one.

    Hope that I could help.
    Cheers

    Gerhard

  7. Kuldeep Bishnoi Says:

    Hi Gerhard,

    I have Oracle.DataAccess.dll version 2.102.2.20.
    I thought of trying this. I was using 9912 KB file
    It takes
    Slow method
    076331.6852 millesec
    Fast method
    129401.37280000001 millesec with 10000 bytes buffer
    639528.18910000008 millesec with 1000 bytes buffer
    073209.825900000011 millesec with 100000 bytes buffer
    064778.7519 1000000 millesec with bytes buffer
    128183.551 2097152 millesec with bytes (2MB) buffer
    So I guess it depends on the buffer size and may be optimum buffer size depends on the network bandwidth between where the code is being executed and where the database is.

    So seems like oracle has fixed it but the question is how did they come so close to the optimum buffer size if they fixed it like you did.
    Thanks

  8. Dave Langer Says:

    Wonderful, just Wonderful… I canot thank you enough for the example.! Im using Oracle.DataAccess.dll version 2.102.2.20 And I read the entire Oracle Data Provider for .Net Developer’s Guide and I was triying to upload pics through an SP and never succided, and never found a working example until now.. a few minutes and was able to upload blobs, Im using the “slow” example as I don’t need to upload big files, just some faces pics for a Human Resources System that Im building. Thanks Again

  9. Usman Says:

    Thank you for the article. It really helped me.

    Is there a way to callan ‘Oracle form’ from a C# program? (just like we spawn another .EXE program)

    Pls. guide,

    Regards

    Usman


Leave a Reply