web-dev-qa-db-fra.com

Le plan d'exécution de l'indice de recouvrement change d'exécution mais n'est pas utilisé

J'ai la requête de course parfois lente de temps prochaine:

SELECT C.CustomerID 
FROM dbo.Customers C WITH (NOLOCK)
WHERE C.Forename = @Forename
    AND C.Surname = @Surname
OPTION (RECOMPILE)

CustomerID est la principale clé de la table des clients. La table des clients dispose également des deux index non clusters suivants:

CREATE NONCLUSTERED INDEX idx_Forename ON Customers (Forename ASC)
CREATE NONCLUSTERED INDEX idx_Surname ON Customers (Surname ASC)

Lorsque j'exécute la requête avec un nom de famille et le prénom entré, la requête optimiseur utilise l'index 'IDX_SEname' comme dans le plan d'exécution suivant:

Execution Plan without covering index

Cette requête prend plus de deux minutes à compléter pour cette recherche particulière et ne trouve aucun résultat. Pour que les valeurs entrées @Forename ne contiennent aucune correspondance dans la table des clients tandis que @seut correspond à 31 182 enregistrements. Lorsque je recherche uniquement par le nom @ du nom, les 31 162 enregistrements se rendent en dessous une seconde avec le plan suivant:

Execution Plan surname only search

Dans une tentative d'optimisation de la requête pour les recherches contenant le prénom et le nom de famille J'ai ajouté l'index de couverture suivant:

CREATE NONCLUSTERED INDEX idx_Surname_Covering ON dbo.Customers (Surname) INCLUDE (Forename)

La requête avec le prénom et le nom de famille revient alors en moins d'une seconde. Cependant, l'indice de couverture n'est pas utilisé dans le plan d'exécution réel:

Execution Plan with covering index

Alors,

  1. L'indice de couverture est-il requis ou existe-t-il un meilleur moyen d'améliorer la performance et
  2. Pourquoi l'index de couverture supplémentaire provoque-t-il le changement d'indice dans le plan d'exécution réel de IDX_FORENAMA Nom à IDX_SEname?

p.s. La requête ci-dessus est un exemple isolé, lorsqu'elle est utilisée soit nom de famille ou prénomètre, soit la recherche des deux pour lesquelles la table des clients inclut également d'autres colonnes interrogeables avec leurs propres index. Ce détail n'a pas été considéré comme pertinent pour la question que je ne l'ai donc pas inclus.

4
Fletch

1) L'indice de couverture est-il requis ou existe-t-il un meilleur moyen d'améliorer la performance?

meilleur index

Le meilleur indice serait l'index sélectif le plus recouvrant des requêtes accédant à la table.

Prenons par exemple dans votre table, vous avez 50000 lignes où le prénom = John, mais un seul où le nom de famille = 'McClane', devriez-vous créer l'index avec John comme la première valeur clé ou McClane?

Réponse:

Cela dépend ... Si vous recherchez toujours John McClane, alors c'est un cas ouvert et fermé d'indexer le nom d'autre nom. Mais que se passe-t-il s'il y a aussi des requêtes à la recherche de Constanthin Smith? Vous pourriez avoir plus de 5000 Smiths, mais seulement cinq constanthines.

En conséquence, cela dépend de vos questions et de ce que vous recherchez, combien ils sont exécutés, ....

Si vos requêtes sont toujours recherchées sur le prénom et le nom de famille, c'est le cas simple de choisir plus sélectif comme la première colonne de clé. Gardez à l'esprit que la lecture de la performance s'améliorer doit rester plus grande que la baisse de la performance en écriture.

Bien sûr, personne ne vous limite à créer deux index, un avec (prénom, nom) et un avec (nom Nom, prénom).

(les instructions de mise à jour/insertion/supprimer/supprimeraient-la).

Ne tenez pas compte des index filtrés et de ne pas, le meilleur indice de votre exemple serait:

CREATE NONCLUSTERED INDEX idx_Forename_Surname ON dbo.Customers (Forename,Surname)

2) Pourquoi l'index de couverture supplémentaire provoque-t-il le changement d'indice dans le plan d'exécution réel de IDX_FORENAMA sur IDX_SEnName?

Je ne pense pas que c'était juste à cause de l'indice, mais à cause des statistiques créées à la suite de la création d'index.

Même si ces statistiques sont identiques telles que celle du nom IDX_SEname, je suppose que c'est qu'ils sont avec un taux d'échantillon plus important (100), comme ils sont créés avec 'Fullscan'.

Si une statistique de mise à jour automatique s'est produite sur les statistiques créées par l'index idx_Surname, ils auraient pu avoir un taux d'échantillon plus petit, ce qui a entraîné une mauvaise estimation (par exemple, une vitesse d'échantillon de 1%).

Vous pouvez essayer de supprimer le idx_Surname_Covering Index et ses statistiques et mettez à jour les statistiques sur dbo.Customers Avec 100% de taux d'échantillon (Fullscan) pour tester cette théorie.

UPDATE STATISTICS dbo.Customers WITH FULLSCAN

Ce qui évolue, évolue votre plan pour utiliser la meilleure recherche.

Si c'est la raison pour laquelle votre requête a changé, et la mise à jour des statistiques avec FullScan ON Windows n'est pas une option viable, vous pouvez modifier la touche Taux d'échantillon

5
Randi Vertongen