2009-05-14 7 views
2

Je le tableau suivant dans SQL Server 2008:requête SQL n'utilise pas l'index disponible (SQL Server 2008)

Session 
(
sessionid varchar(10) 
startdate dateteime 
enddate dateteime 
--rest of the fields go here 
) 

Je les deux indices nonclustered suivants créé:

Inddex1: SessionID,startdate,enddate 
Inddex2: startdate,enddate 

je la requête suivante

select * 
from session 
where startdate>[email protected] and enddate <[email protected] 

lors de l'exécution de cette requête, ces deux idex ne sont pas utilisés. Le plan de requête affiche uniquement l'analyse de la table.

Maintenant, j'ai essayé de supprimer l'index1 et exécuté le même SP Still index2 n'est pas utilisé.

Des indices sur la façon de rendre le SP à utiliser index2? (Aucune utilisation d'index forcé s'il vous plaît.)

Répondre

3

Avez-vous un index cluster sur la colonne SessionID? Dans ce cas, vos index sont fondamentalement identiques car tout index non cluster inclura implicitement la clé en cluster.

Combien de lignes y a-t-il dans la table et quelle est la cardinalité/l'unicité des valeurs? Si la table est assez petite, une analyse de table peut être plus efficace qu'une recherche d'index + des recherches bookmarp pour récupérer les colonnes restantes.

+0

+ 1 - les petites tables m'ont longtemps jetée parce qu'elles ont refusé d'utiliser les index dans de nombreuses circonstances (pour de bonnes raisons, je suppose) –

0

L'index composite ne sera pas utilisé car il ne peut pas être utilisé pour optimiser cette requête. Vous devriez créer un index séparé sur chaque colonne.

+1

Pas vrai. L'index peut (accent sur mai) être utilisé chaque fois qu'il y a un prédicat sur la première colonne de l'index. Ne doit pas être l'égalité. –

+0

vous avez raison. réponse éditée – hopethisworks

1

Tout d'abord, c'est une bonne idée d'avoir une clé primaire que vous utilisez comme un index cluster unique.

Je ne suis pas sûr d'avoir compris le point de ces deux indices composites. Ne seriez-vous pas mieux avec l'index individuel sur les dates?

0

Vous dites que le processeur de requêtes n'utilise pas l'un de vos index, mais vous ne nous dites pas ce que fait. Je présume un scan de table ...?

Vous n'avez pas d'index de couverture pour votre requête. Parce que vous faites "select *", le processeur de requêtes sait que, au mieux, il ne peut obtenir qu'un "signet" de votre index (l'un ou l'autre des index le ferait), et il devra alors faire une référence croisée avec le signet les pages de données réelles dans votre tableau. Avec cette connaissance, le processeur de requêtes examinera la quantité de données dans votre table. Si la quantité de données est petite (pour une définition de petite taille), alors il peut décider que l'analyse de la table est plus efficace qu'un index recherché par une recherche de signet. Envisagez de modifier la requête et/ou l'index pour ne sélectionner que les champs qui sont entièrement couverts par l'index. Ensuite, je m'attendrais à ce que vous voyiez l'utilisation de l'index. Mais ce n'est pas nécessairement la bonne chose à faire - créer un index énorme pour une requête rarement utilisée peut être faux.

0

Tout index avec "startdate" comme première colonne peut aider avec la recherche de startdate> = @ date1. Tout index avec "enddate" comme première colonne peut aider avec la recherche de "enddate < = @ date2". Mais il n'y a pas d'indice qui puisse aider avec les deux. Et en supposant qu'il n'y ait presque pas de date de fin avec le même startdate, un index sur (startdate, enddate) n'est pas plus utile qu'un index sur (startdate).Par conséquent, l'analyse de la table semble être un bon choix de SQL Server.

Même si vous recherchez startdate> = @ date1, il serait toujours logique de faire une analyse de table. Une analyse d'index vous donnerait beaucoup de références à la table que vous auriez à résoudre, ce qui ne vaut pas la peine pour beaucoup de données.

Une requête qui devrait utiliser l'indice est:

select * from session where startdate = @date1 

Quoi qu'il en soit, si vous pensez que vous savez mieux que l'optimiseur, vous pouvez imposer l'utilisation d'un indice comme:

select * 
from session with (index indexname) 
where startdate>[email protected] and enddate <[email protected] 
+1

Pas vrai. Et index like (startdate, enddate) est idéal pour une requête avec un prédicat qui filtre sur startdate en premier et enddate en second. L'index peut être utilisé. S'il y a beaucoup de colonnes, filtrer sur cet index seul et faire des recherches de signets pour les résultats sera beaucoup moins cher E/S que de faire une analyse de table complète. –

+0

Cela aiderait avec "stardate = @a et enddate <@b", et cela empêcherait la recherche de table dans "select enddate où startdate> @x". Alors oui, il y a de rares exceptions. – Andomar

+0

Il aidera également dans sa requête exacte. ayant un indice comme (startdate, enddate) aider dans une will requête avec un prédicat comme WHERE startdate> = @StartDate ET enddate <= @EndDate Puisque l'indice est fondamentalement juste des données triées, il est une façon beaucoup plus rapide de filtrage les données. En utilisant le premier prédicat et l'index, nous trouvons toutes les données qui remplissent le premier prédicat. Étant donné l'index, les données trouvées sont maintenant triées en fonction du second prédicat, et nous pouvons donc le filtrer à nouveau. –