简体   繁体   中英

Eliminate Clustered Index Scan in query

I have this query involving 2 tables joined.

Select  q.id, 
                         q.LastUpdatedTicksSinceEpoch,
                            q.[Type] [QuoteType],
       q.LatestFormData [FormDataJson], 
                            q.QuoteNumber, 
                            q.QuoteState,
       q.policyId,
                            p.CustomerId, 
                            p.CustomerFullName, 
                            p.CustomerAlternativeEmail,
                            p.CustomerHomePhone,
                            p.CustomerMobilePhone,
                            p.CustomerWorkPhone,
                            p.CustomerPreferredName,
       p.ProductId
                            from Quotes q
                    INNER JOIN  PolicyReadModels p on q.PolicyId=p.id
                    where
                            p.TenantId = @TenantId
                            and p.Environment = @Environment
                           and q.LastUpdatedTicksSinceEpoch > @LastUpdatedTicksSinceEpoch
         and q.QuoteState <> 'Nascent'
                            and q.QuoteNumber is not null
                            and q.IsDiscarded = 0
     ORDER BY q.LastUpdatedTicksSinceEpoch

When I run it and get the execution plan, I see Clustered Index Scan - which I want to Eliminate and use an Index Seek.

How can I eliminate the clustered index scan here? How can I construct a new INDEX? To add more context to this, this will query will be called by 12 parallel thread(12 connections), so I need this fast and optimized.

Here is my Query and execution plan:

https://www.brentozar.com/pastetheplan/?id=HkWjdvKDD

Create an index on:

create index someIndex on
Quotes (LastUpdatedTicksSinceEpoch)
include (Id, Type, LatestFormData, QuoteNumber, QuoteState, PolicyId, IsDiscarded)
where IsDiscarded = 0
                      

This

  • Filters by your two fixed values (QuoteNumber NOT NULL and IsDiscarded = 0)
  • Sorts the data by LastUpdatedTicksSinceEpoch (as you are passing a variable to that in your WHERE clause, and it appears the most likely one you want to sort on
  • Includes all other relevant fields so doesn't need to go back to the clustered index (eg, becomes a covering index).

Note that quote.ID is not included as it is your PK (from what I can tell in the execution plan) and therefore implicitly included in the index. You can include it though - no harm done at all (eg, index size and performance will be exactly the same).

CREATE INDEX IX_q ON Quotes 
    (
    LastUpdatedTicksSinceEpoch
    )
INCLUDE
    (
    PolicyId,
    [Type],
    QuoteState,
    LatestFormData,
    QuoteNumber,
    IsDiscarded
    )
WHERE 
    (
    QuoteNumber is not null 
    AND IsDiscarded = 0
    )

Note: I think this is probably the fastest you can get, but you need to be careful because more indexes on table mean slower inserts, updates and deletes.

Often I find a much shorter index that can be used in many places is preferable to a very specific index like this (remember, if some fields like LatestFormData are large, then this index can get bloated and not be as useful to other queries).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM