views:

172

answers:

5

Let's have:

  • $DB an SQL Server database
  • $DBSP1 an SQL Server database containing stored procedures referencing $DB
  • $DBSP2 is exactly like $DBSP1
  • $SP is a stored procedure

Running $SP on $DBSP1 from C# code takes around 1.5s.

Running $SP on $DBSP2 from C# code takes around 0.5s.

The C# code is very simple and use SqlClient with default parameters.

When I execute $SP in an SQL console on both $DBSP1 and $DBSP2, it takes 0.4s.

The only difference between the two code databases is $DBSP1 is in production and is a bit loaded, while $DBSP2 is idle. There is no data in code databases, only stored procedures and views over $DB.

Can someone suggest reasons why this happen? Since all the work happens in $DB which is equally loaded in both cases I would expect performances to be similar.

A: 

I think you have your answer. $DBSP1 is busy. It still has to task switch and prioritize work that comes in even though most of the work is happening in $DB.

Further, depending on the amount of data being transferred, the network activity comes into play. If $DBSP1 is sending / receiving a fair amount of data, that lessens the amount of available bandwidth for it to communicate with $DB and will cause result sets to transfer slower.

Chris Lively
I forgot to say that all databases are on the same machine. I could not measure any difference when artifially cropping the stored procedure output (in order to reduce the SP output).I agree with you that it seems that a code database performance degrades independantly of the referenced database load. I just wonder if anyone know why.An obvious but stupid solution is to create N similar code databases and balance the load over them. But this is too stupid for me to consider.
pmezard
A: 

1) Check that both servers have the same indexes defined on each table

2) Rebuild Indexes (or at a minimum, update Statistics)

Do you have regular index maintenance jobs scheduled? Sounds like out of date statistics or fragmented indexes are causing the discrepancy..

Mitch Wheat
That was my first thought, but don't forget:"When I execute $SP in an SQL console on both $DBSP1 and $DBSP2, it takes 0.4s."So the discrepancy is not in the machines' respective SQL Server configurations/environments. It must be something in the application's runtime environment (I presume ASP.NET, but he hasn't specified)
John Booty
The performance discrepancies happens between two code databases without any data. So no, indexes are not the problem here.
pmezard
@John Booty: "Running $SP on $DBSP1 from C# code takes around 1.5s. Running $SP on $DBSP2 from C# code takes around 0.5s." that is exactly the symptom of incorrect param sniffing and old statistics. –
Mitch Wheat
@ pmezard : "The performance discrepancies happens between two code databases without any data" - that statement makes no sense!
Mitch Wheat
@Mitch Wheat: what I meant is there is no index in the code database. Now, you are right there might be issues with the SP query plans and statistics. I am surprised because $DBSP2 is much younger than $DBSP1 but performs better. And because executing the same SP in an SQL console takes the same time in both case. So that would rule out statistics for me.
pmezard
A: 

Suggest you run profiler to see what is happening, but often the workload on a production database makes everything run slower. Also statistics may be out of date. Performance is rarely the same between two servers in my experience.

HLGEM
Since both requests take the same time from an SQL console in both cases, I would rule out query plant/statistics issues. Still, running the profiler may bring in lots of interesting information. Could you suggest events to look at? Perhaps something related to login time/wait?
pmezard
A: 

Measure.

Add SET STATISTICS TIME ON and SET STATISTICS IO ON to your C# and on the sql console call as well. In C#, hook up the SqlConneciton.InfoMessage event to capture the informational messages and display them. also separate the time measured for the SqlConnection.Open() call and the SqlCommand.ExecuteNonQuery call.

Then you'll be able to tell the difference.

  • different conenction Open() times?
  • different compilation/execution times ?
  • different logical reads/physical reads ratio?
  • different logical reads count?
Remus Rusanu
+1  A: 

The difference in speed came from different query plans. $SP is a complicated stored procedure and its initial query plan may vary vastly depending on the first query hitting it. And at this point we were not controlling the first request since right after deploying the $SP, it was published in production.

We tried providing hints about $SP parameters both at $SP levels and query levels, without success. So instead, we warm up the $SP before deploying with well crafted queries known to generate the correct query plan.

pmezard