3

I have a stored procedure on a busy database which constantly come out top in the list of expensive queries (by some way). The query is very simple, it takes a single parameter (@ID, int) which is the primary key of the table, and selects the record that matches that ID. The primary key is an identity field with a clustered index, so I am stumped as to how to optimise this any further?

The query is as follows

CREATE PROCEDURE [dbo].[P_Call_Get]

    @ID int = null

AS

    select ID,
        AppID,
        AgentID,
        AgentLogin,
        Ext,
        VDN,
        VDNName,
        Skill,
        SkillName,
        CallFrom,
        TelNoFrom,
        ParentCallID,
        CallStart,
        ACWStart,
        CallEnd,
        Outcome,
        StageID,
        TxTo,
        TxSuccess,
        ServiceID,
        DiallerID,
        CRC,
        TSCallID,
        CallDirection,
        [Manual],
        CallBackAgent,
        CallBackDateTime,
        Notes
    from P_Call
    where (ID = @ID or @ID is null)

Not sure the best way to post the execution plan - all it shows is that 100% of the operation is taken up by the clustered index scan

6
  • 1
    Could you post the code? Commented May 7, 2010 at 11:21
  • 1
    Can you post the Query and the execution plan? Commented May 7, 2010 at 11:21
  • 1
    when you say it was the most expensive, how many reads was it doing? How often is it called? Commented May 7, 2010 at 11:28
  • could it be that it appears to be the most expensive due to the high frequency of use? If it's doing 10 logical I/O but running 10,000,000 times a day, it might look expensive, but really it's probably fine. Commented May 7, 2010 at 11:39
  • It is called a lot! it will be called at least once per agent per call in a call centre with 100 agents taking 3 - 400 calls each per day Commented May 7, 2010 at 11:40

4 Answers 4

8

I think that by using where (ID = @ID or @ID is null) you are getting a sub optimal plan. Divide this into 2 separate queries so that in the case where @Id is not null it will just look it up directly and you will get a seek rather than a scan appear in the plan. You could maybe create a View with the columns you require to avoid the repetition (i.e. the Query without any where clause)

select ID,
    AppID,
    AgentID,
    AgentLogin,
    Ext,
    VDN,
    VDNName,
    Skill,
    SkillName,
    CallFrom,
    TelNoFrom,
    ParentCallID,
    CallStart,
    ACWStart,
    CallEnd,
    Outcome,
    StageID,
    TxTo,
    TxSuccess,
    ServiceID,
    DiallerID,
    CRC,
    TSCallID,
    CallDirection,
    [Manual],
    CallBackAgent,
    CallBackDateTime,
    Notes
from P_Call
Sign up to request clarification or add additional context in comments.

3 Comments

Splitting into 2 queries did exactly that - I now get a seek rather than a scan in my execution plan. Which scares me a little as I have used this approach in a number of SPs which search on a number of optional criteria. Was going to ask about a better approach but I think optimising these is a separate question
I'm not sure if there is any way around the splitting into 2 queries approach. It can be a bit of a pain to keep complex queries in synch though especially if you are using this approach for multiple parameters in the query.
@Macros There is no way of avoiding the split - SQL server only normally maintains a single execution plan per statement.
1

Try cleaning out procedure cache and memory buffers:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

Doing so before testing your procedure's performance will prevent the use of cached execution plans and previous results cache.

Comments

0

can you use table partion. it may fixed the issue.

Comments

0

How many rows are in the table? You do realize that a "clustered index scan" = full table scan.

2 Comments

I didn't...but do now! have spent the last 2 days optimising SPs based on this
Good deal. You probably already figured it out why but I should have explained why the optimizer was selecting a sub optimal plan. The reason the index cannot be used is the (or @ID is null) portion of the WHERE clause. NULL values are not indexed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.