0

I have a stored procedure which contain so many SET statements. That is taking so long to execute. What I can do for increase the performance. One statement I have included here.

SET @VisitedOutlets=(select count (distinct CustomerId) from dbo.VisitDetail  
                        where RouteId = @intRouteID   
                        and CONVERT(VARCHAR(10),VisitDate,111) between CONVERT(VARCHAR(10),@FromDate,111)  
                        and CONVERT(VARCHAR(10),@ToDate,111)); 
Matt Allwood
  • 1,448
  • 12
  • 25
Tom
  • 1,343
  • 1
  • 18
  • 37

2 Answers2

0

I think your problem comes from the fact that you are using variables in your query. Normally, the optimizer will ... optimize (!) the query for a given (hard coded) value (let's say id = 123) for instance, whereas it cannot optimize since it is a variable.

Let's take a great example from here :

OK,

  1. You are the Optimizer and the Query Plan is a vehicle.

  2. I will give you a query and you have to choose the vehicle.

  3. All the books in the library have a sequential number

My query is Go to the library and get me all the books between 3 and 5

You'd pick a bike right, quick, cheap, efficient and big enough to carry back 3 books.

New query.

Go to the library and get all the books between @x and @y.

Pick the vehicle.

Go ahead.

That's what happens. Do you pick a dump truck in case I ask for books between 1 and Maxvalue? That's overkill if x=3 and y=5. SQL has to pick the plan before it sees the numbers.

So your problem is that the optimizer cannot do its job correctly. To allow him doing his job, you can make him recompile, or update statistics. See here, here, and here.

So my 2 solutions to your problem would be :

  1. Recompile : OPTION(RECOMPILE)

  2. Update statistics : EXEC sp_updatestats

Community
  • 1
  • 1
Pholochtairze
  • 1,836
  • 1
  • 14
  • 18
0

Your query is essentially:

select @VisitedOutlets= count(distinct CustomerId)
from dbo.VisitDetail  
where RouteId = @intRouteID and 
      CONVERT(VARCHAR(10), VisitDate, 111) between
          CONVERT(VARCHAR(10), @FromDate, 111) and CONVERT(VARCHAR(10), @ToDate, 111);

I think this query can be optimized to take advantage of indexes. One major problem is the date comparison. You should not be doing any conversion for the comparison on VisitDate. So, I would rewrite the query as:

select @VisitedOutlets= count(distinct CustomerId)
from dbo.VisitDetail vd
where vd.RouteId = @intRouteID and 
      vd.VisitDate >= cast(@FromDate as date) and
      vd.VisitDate < dateadd(day, 1, cast(@ToDate as date))

For this query, you want an index on VisitDetail(RouteId, VisitDate, CustomerId). I would also store the constants in the appropriate format, so conversions are not needed in the query itself.

between is dangerous when using dates. Here is an interesting discussion on the topic by Aaron Bertrand.

Community
  • 1
  • 1
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786