Why is some sql query much slower when used with SqlCommand?

谁说胖子不能爱 提交于 2019-11-26 11:04:29

问题


I have a stored procedure that executes much faster from Sql Server Management Studio (2 seconds) than when run with System.Data.SqlClient.SqlCommand (times out after 2 minutes).

What could be the reason for this?


Details: In Sql Server Management Studio this runs in 2 seconds (on production database):

EXEC sp_Stat
    @DepartmentID = NULL

In .NET/C# the following times out after 2 minutes (on production database):

string selectCommand = @\"
EXEC sp_Stat
    @DepartmentID = NULL\";
string connectionString = \"server=***;database=***;user id=***;pwd=***\";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlCommand command = new SqlCommand(selectCommand, connection))
    {
        connection.Open();
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
            }
        }
    }
}

I also tried with selectCommand = \"sp_Stat\", CommandType = StoredProcedure, and an SqlParameter, but it\'s the same result.

And without EXEC it\'s the same result as well.

On an almost data-empty development database both cases finishes in less than 1 second. So it\'s related to that there\'s a lot of data in the database, but it seems to only happen from .NET...


What Marc Gravell wrote about different SET values makes the difference in the presented case.

SQL Server Profiler showed that Sql Server Management Studio runs the following SET\'s that .NET Sql Client Data Provider does not:


SET ROWCOUNT 0 
SET TEXTSIZE 2147483647 
SET NOCOUNT OFF 
SET CONCAT_NULL_YIELDS_NULL ON 
SET ARITHABORT ON 
SET LOCK_TIMEOUT -1 
SET QUERY_GOVERNOR_COST_LIMIT 0 
SET DEADLOCK_PRIORITY NORMAL 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
SET ANSI_NULLS ON 
SET ANSI_NULL_DFLT_ON ON 
SET ANSI_PADDING ON 
SET ANSI_WARNINGS ON 
SET CURSOR_CLOSE_ON_COMMIT OFF 
SET IMPLICIT_TRANSACTIONS OFF 
SET QUOTED_IDENTIFIER ON
SET NOEXEC, PARSEONLY, FMTONLY OFF

When I included these, the same query took the same amount of time in SSMS and .NET. And the responsible SET is ...

SET ARITHABORT ON

What have I learnt? Maybe to use a profiler instead of guessing...

(The solution at first seemed to be related to parameter sniffing. But I had mixed some things up...)


回答1:


Another thing that can be important is the SET options that are enabled. Some of these options change the query plan sufficiently to change the profile. Some can have a huge impact if you are looking at (for example) a calculated + persisted (and possibly indexed) column: if the SET options aren't compatible, it can be forced to re-calculate the values, rather than using the indexed value - which can change an index seek into a table scan + calculation.

Try using the profiler to see what SET options are "in play", and see if using those options changes things.

Another impact is the connection string; for example, if you enable MARS that can change the behaviour in subtle ways.

Finally, transactions (implicit (TransactionScope) or explicit) can have a huge impact, depending on the isolation level.




回答2:


This is almost certainly due to an 'incorrect' cached query plan. This has come up on SO quite a few times.

Do you have up-to-date statistics? A regular scheduled index maintenance plan?

You can test if it is definitely due to the cached query plan by adding this to your stored procedure definition:

CREATE PROCEDURE usp_MyProcedure WITH RECOMPILE...

This will re-index an entire database (caution if database is very large!):

exec sp_msforeachtable "dbcc dbreindex('?')"

SO posts:

Big difference in execution time of stored proc between Managment Studio and TableAdapter.

Parameter Sniffing (or Spoofing) in SQL Server

optimize for unknown for SQL Server 2005?

Different Execution Plan for the same Stored Procedure




回答3:


Had a similar issue and it turns out having MultipleActiveResultSets=true in the connection string (which is supposed to have minimal impact) was making pulling 1.5mil records over a remote connection take 25 minutes instead of around 2 minutes.




回答4:


We had a similiar issue, where a query would complete in 2 seconds in SSMS and take more than 90 seconds when called from a .NET client (we wrote several VB/C# apps/sites to test it.)

We suspected that the query plan would be different, and rewrote the query with explicit looping ("inner loop join" and "with index") hints. This solved the problem.



来源:https://stackoverflow.com/questions/801909/why-is-some-sql-query-much-slower-when-used-with-sqlcommand

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!