A Precarious Balance

Sean Winstead's web site & blog
Welcome to A Precarious Balance Sign in | Join | Help
in Search

A Precarious Balance

Sean Winstead's web site & blog

SqlDataAdapter.Fill has slow performance

This post falls into the category of "Solution for a technical issue for which I found no help on the Internet".

Overview

If you're using adhoc SqlParameters with a SqlDataAdapter and notice that calls to the SqlDataAdapter's Fill method take longer than expected, try using a typed SqlParameter instead of an adhoc SqlParameter.

Example of an adhoc SqlParameter:

      adapter.Parameters.Add("@WMSReceiptID", wmsReceiptID);

Example of a typed SqlParameter:

      SqlParameter parameter = adapter.SelectCommand.Parameters.Add("@WMSReceiptID", SqlDbType.VarChar, 64);
      parameter.Value = wmsReceiptID;
      adapter.Parameters.Add(parameter);

When using an adhoc SqlParameter, the ADO.NET implementation grabs schema information. In this case, it led to SqlAdapter.Fill taking 20 seconds to execute. I switched in the typed SqlParameter and execution speed returned to normal.

The gory details

Today I tested a bug fix on a search screen. The business layer builds a dynamic query based upon the search criteria entered by the user. With shock, I noticed that it was taking 20 seconds to perform the search. The request was carried out across a VPN connection to the customer's network, but it had never taken 20 seconds to execute this query.

At first I thought it was a dormant problem with the SQL that finally decided to wake up. But when executed via SQL Query Analyzer, the query completed in 1 or 2 seconds.

To isolate the problem, I threw the code into a console application. The code uses a SqlDataAdapter to fill a DataTable. The particular instance of this query had one parameter that was filled via an ad hoc SqlParameter.

Following is a stripped down version of the test code...

      SqlConnection connection = new SqlConnection(Database.ConnectionString);
      try 
      {
        connection.Open();
        SqlDataAdapter adapter = new SqlDataAdapter();
        adapter.SelectCommand =
          new SqlCommand("SELECT ...", connection);

        adapter.SelectCommand.Parameters.Add("@WMSReceiptID", "[SomeRecordID]");
        DataTable table = new DataTable();
        try
        {
          adapter.Fill(table);
        }
        catch (Exception E)
        {
          Console.WriteLine("Error: " + E.Message);
        }
      }
      finally 
      {
        connection.Close();
      }

The test program also took 20 seconds or so to execute the source code line "adapter.Fill(table);".  For kicks, I removed the SqlParameter and hardcoded the receipt ID. Bam! The call to adapter.Fill returned in 1 second.

Hmmm. Why would using a SqlParameter cause slow performance? I've used them hundreds, if not thousands of them, with no slowdown.

I downloaded a trial version of Automated QA's AQTime and profiled the test application. AQTime reported a large amount of time in UnsafeNativeMethods/Dbnetlib::ConnectionRead. I used the Call Graph to backtrack. Once I reached method SqlDataReader.get_MetaData. I reasoned that the adhoc SqlParameter was causing ADO.NET to fetch the schema information and doing so was taking a lot of time.

I switched to a typed SqlParameter and performance went back to its expected level.

--
Sean Winstead

Tags: ADO.NET, .NET, SQL Server

Published Sunday, January 15, 2006 11:30 AM by Sean Winstead
Filed under: , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

ChannelMAX said:

I have the exact same scenario. The SQL in 1 sec from SQL server Management Studio with all values hard coded, but from Adapter.Fill, it takes 30 to 40 secs. But I don't understand what you mean by "typed SqlParameter" .. Would you please provide snippet of your fine tuned code ? Thanks a lot ..

I have checked this site http://www.sqlservercentral.com/columnists/rVasant/workingwithsqlparameterinnet.asp. But not understanding the meaning of "typed SQLParameter".
August 16, 2006 2:18 AM
 

Sean Winstead said:

Hi ChannelMAX,

By a typed parameter, I mean that when you create the SqlParameter in code, you tell it what type of value it contains. The example in the post has the following line of source code:

SqlParameter parameter = adapter.SelectCommand.Parameters.Add("@WMSReceiptID", SqlDbType.VarChar, 64);

I call this a typed parameter because we are passing SqlDbType.VarChar into the Add method.
August 17, 2006 12:22 AM
 

parke said:

thank youuu

August 30, 2008 12:58 AM
 

SD said:

Holy cow. You saved my life. I was getting timeouts on queries that super fast in Query Analyzer.

Terrific problem solving.

October 15, 2008 6:27 PM
 

kris said:

Hello, I have the same problem. It is interesting, that if I using Adapter.Fill(...) client tooks about 30 seconds and if I using command.ExecuteReader() it took less than 1 second .I have solve it by recompile stored procedure. I think it's bag.

March 27, 2009 1:35 AM
 

BF said:

I had this problem as well (except the sqlcommand was calling a stored procedure)  and found that the 'typed paramters' solution did not have any effect.

With SP's it seems that the procedure can be cached and it may need recompiling.

In the end we found that clearing the procedure cache made a HUGE difference and brought the ado.net execution time right down.

In the SSMS run:

DBCC DROPCLEANBUFFERS

DBCC FREEPROCCACHE

May 20, 2009 10:31 PM
 

BD said:

I am having the exact same problem, but my app is already using typed params.  Any thoughts?

April 16, 2010 11:51 AM
 

bd said:

My queries really were that slow.  Be wary of cached results when pulling from SSMS as I found in this link http://stackoverflow.com/questions/250713/sqldataadapter-fill-method-slow

April 16, 2010 12:00 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit