Question

Je suis en train d'améliorer la performance sur une requête qui exécute très lentement. Après avoir traversé le Plan d'exécution réel ; Je trouve que Clustered Index Seek prenait 82%. Est-il possible pour moi d'améliorer la performance sur un Index Seek ? Ci-dessous une image du problème Index Seek à partir du plan d'exécution ainsi que l'index et la table qu'il utilise.

alt texte http://img340.imageshack.us/img340/1346/seek. PNG

Index:

/****** Object:  Index [IX_Stu]    Script Date: 12/28/2009 11:11:43 ******/
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu] 
(
 [StuKey] ASC
)WITH (PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

Tableau (quelques colonnes omis par souci de concision):

CREATE TABLE [dbo].[stu](
 [StuCertKey] [int] IDENTITY(1,1) NOT NULL,
 [StuKey] [int] NULL
 CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED 
(
 [StuCertKey] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
Était-ce utile?

La solution

Je généralise, mais ...

A chercher index ordonné en clusters est, pour la plupart, le scénario le plus optimiste. La seule façon que je peux penser à améliorer les performances seraient:

  • Mettre à jour la requête, si possible de revenir moins de lignes / colonnes;
  • Défragmenter ou reconstruire l'index;
  • partitionne l'index sur plusieurs disques / serveurs.

Si elle est seulement le retour 138 lignes, et il est lent que ... peut-être qu'il est bloqué par un autre processus? Testez-vous cela dans l'isolement, ou sont les autres utilisateurs / processus en ligne en même temps? Ou peut-être même un problème matériel, comme une panne de disque.

Autres conseils

index cluster cherche se produire lorsque les index non-cluster sont utilisés et ne sont pas nécessairement mauvais.

Considérez la requête suivante:

SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX'

S'il n'y a qu'un index cluster sur Stukey, puis l'option Sql serveur a seulement 1, il doit balayer toute la table à la recherche de lignes où l'Etat = "TX » et retour ces lignes.

Si vous ajoutez un index non cluster sur l'état

CREATE INDEX IX_Stu_State on Stu (State)

serveur Maintenant Sql a une nouvelle option. Il peut choisir de demander l'aide de l'index non-cluster, qui produira les lignes où l'Etat = « TX ». Toutefois, afin d'obtenir les colonnes restantes pour revenir dans le SELECT, il doit regarder ces colonnes en faisant un index ordonné en clusters cherchent pour chaque ligne.

Si vous voulez réduire l'index cluster cherche, alors vous pouvez faire votre index « couverture » en incluant des colonnes supplémentaires en elle.

 CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )

Cet index contient maintenant toutes les colonnes nécessaires pour répondre à la question ci-dessus. La requête fera un index cherchent à retourner uniquement les lignes où l'Etat = « TX », et les colonnes supplémentaires peuvent être retirées de l'index non cluster, de sorte que l'index cluster cherche aller.

Un index ordonné en clusters plage recherche qui retourne 138 lignes ne sont pas votre problème.

Techniquement, vous pouvez améliorer la performance en faisant rechercher l'index cluster plus étroit:

  • evict all varlenght dans une unité d'allocation distincte en définissant les types de valeur ' sur rangée » à 1 et de recréer la table à partir de zéro).
  • (SQL 2008 EE seulement).

Les deux peuvent avoir tout à fait un impact dramatique sur la gamme temps de recherche, car ils réduisent l'IO et la nécessité de frapper lit physique. Bien sûr, comme d'habitude, le résultat varie sur un grand nombre d'autres facteurs, comme les colonnes font votre projet (expulsant une colonne projetée dans l'unité d'allocation de blob peut effectivement avoir des effets négatifs sur certaines requêtes). Comme une note de côté, généralement la fragmentation aura un impact marginal sur une telle analyse à courte portée. Encore une fois, cela dépend.

Mais comme je le dis, je doute fort que cela est votre vrai problème. Vous avez seulement affiché certaines parties du plan et les résultats de votre propre analyse. La vraie cause racine peut mettre complètement ailleurs.

Pensées ...

  • Pourquoi IX_Stu cluster? En interne, SQL Server ajoute un « uniqueifier » 4 octets à index clusterisés non uniques. Quelle est la justification? Cela a également bloats votre PK trop

  • Quel est le

    requête réelle que vous utilisez?
  • Enfin, pourquoi FILLFACTOR 80%?

Edit:

  • Un FILLFACTOR "normal" serait de 90%, mais ceci est une règle générale que

  • Une requête de jointure 11? Ce qui est le plus probable que votre problème. Quelles sont vos JOIN, clauses WHERE etc? Quel est le plan en texte intégral?

Quelques conseils généraux: quand je dois faire l'optimisation des requêtes, je commence par écrire ce que je pense que le plan d'exécution devrait être.

Une fois que je l'ai décidé ce que je pense que le plan d'exécution devrait être, j'essaie de faire la requête réel.adapter ce plan. Les techniques de le faire sont différentes pour chaque SGBD, et ne transfèrent pas nécessairement de l'un à l'autre, ou même, parfois, entre les différentes versions du SGBD.

La chose à garder à l'esprit est que le SGBD ne peut exécuter une jointure à la fois: il commence par deux tables initiales, se joint à ceux-ci, et prend alors le résultat de cette opération et se joint à la table suivante. L'objectif à chaque étape est de minimiser le nombre de lignes dans le jeu de résultats intermédiaire (plus exactement, afin de minimiser le nombre de blocs qui doivent être lus afin de produire des résultats intermédiaires, mais cela signifie généralement moins de lignes).

Avez-vous essayé un peu d'entretien sur cet indice? Comme il défragmenter? Il semble vraiment étrange que cela coûte tant que ça (120,381). Recherche d'index est l'opération d'index le plus rapide, ne devrait pas prendre longtemps. Pouvez-vous poster la requête?

Qu'est-ce qui se passe si vous coder en dur WHERE critères, comme celui-ci:

SELECT StuCertKey, StuKey FROM stu 
WHERE stuKey in (/* list 50 values of StuKey here */)

S'il est encore très lent, vous avez un problème interne d'une certaine sorte. S'il est plus rapide, l'indice n'est pas votre goulot d'étranglement, il est JOIN que vous faites pour créer le WHERE Filtre.

Notez que SELECT * peut être très lent s'il y a beaucoup de grandes colonnes, et surtout s'il y a BLOBs.

Vérifier les statictics d'index.

recalculant les statistiques index cluster va résoudre le problème.

dans mon cas, je cherchais 30 dossiers à 40M recored. le plan d'exécution dit qu'il va à travers l'index cluster, mais il a fallu environ 200ms. et l'indice n'a pas été défragmenté. après avoir recalculé il de statistiques, il devient fait sous 10ms!

Reconstruire l'index, et calculer les statistiques?

La seule autre façon que je peux penser à l'accélérer est de partitionner la table, qui peut ou peut ne pas être possible.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top