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
May 2, 2006 at 12:54 pm
[...] Slow Oracle BLOB upload with C# .NET and how to speed up. [...]
July 19, 2006 at 6:35 pm
[...] 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… . [...]
August 7, 2006 at 11:59 pm
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.
August 8, 2006 at 6:25 am
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
September 7, 2006 at 5:22 am
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
September 7, 2006 at 5:26 am
That should read the Oracle.DataAccess.dll
September 7, 2006 at 5:43 am
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
September 13, 2007 at 2:09 pm
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
February 15, 2008 at 3:14 pm
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
March 13, 2008 at 7:33 am
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