Same query uses different indexes?

indexing, sql, sql-server, sql-server-2005

Solution

Details on indexes are stored as statistics in a histogram-type dataset in SQL Server.

Each index is chunked into ranges, and each range contains a summary of the key values within that range, things like:

- range High value

- number of values in the range

- number of distinct values in the range (cardinality)

- number of values equal to the High value

...and so on.

You can view the statistics on a given index with:

DBCC SHOW_STATISTICS(<tablename>, <indexname>)

Each index has a couple of characteristics like density, and ultimately selectivity, that tell the query optimiser how unique each value in an index is likely to be, and how efficient this index is at quickly locating records.

As your query has three columns in the where clause, it's likely that any of these columns might have an index that could be useful to the optimiser. It's also likely that the primary key index will be considered, in the event of the selectivity of other indexes not being high enough.

Ultimately, it boils down to the optimiser making a quick judgement call on how many page reads will be necessary to read each your non-clustered indexes + bookmark lookups, with comparisons with the other values, vs. doing a table scan.

The statistics that these judgements are based on can vary wildly too; SQL Server, by default, only samples a small percentage of any significant table's rows, so the selectivity of that index might not be representative of the whole. This is particularly problematic where you have highly non-unique keys in the index.

In this specific case, I'm guessing your `typeenvoi` index is highly non-unique. This being so, the statistics gathered probably indicate to the optimiser that one of the values is rarer than the other, and the likelihood of that index being chosen is increased.

Problem

Can a select query use different indexes if a change the value of a where condition? The two following queries use different indexes and the only difference is the value of the condition and typeenvoi='EXPORT' or and typeenvoi='MAIL' ``` select numenvoi,adrdest,nomdest,etat,nbessais,numappel,description,typeperiode,datedebut,datefin,codeetat,codecontrat,typeenvoi,dateentree,dateemission,typedoc,numdiffusion,nature,commentaire,criselcomp,crisite,criservice,chrono,codelangueetat,piecejointe, sujetmail, textemail from v_envoiautomate where etat=0 and typeenvoi='EXPORT' and nbessais<1 select numenvoi,adrdest,nomdest,etat,nbessais,numappel,description,typeperiode,datedebut,datefin,codeetat,codecontrat,typeenvoi,dateentree,dateemission,typedoc,numdiffusion,nature,commentaire,criselcomp,crisite,criservice,chrono,codelangueetat,piecejointe, sujetmail, textemail from v_envoiautomate where etat=0 and typeenvoi='MAIL' and nbessais<1 ``` Can anyone give me an explanation?

Original source