2009-05-26 6 views
1

La requête MSSQL2005 ci-dessous est très lente. Je pense que leur devrait être un moyen de l'accélérer, mais je ne sais pas comment. Notez que j'ai édité la jointure interne pour utiliser des instructions select pour rendre plus évident (aux personnes lisant cette question) ce qui se passe, bien que cela n'a aucun impact sur la vitesse (le plan d'exécution est probablement le même). Fait intéressant, je n'utilise jamais les groupes de mots-clés pour quelque chose de plus qu'un compte, mais je ne suis pas sûr qu'il existe un moyen de tirer parti de cela.Requête SQL Optimization

select top 1 cde.processPath as 'keywordValue', count(*) as 'total' 
from dbo.ClientDefinitionEntry AS cde INNER JOIN dbo.KeywordValueGroups AS kvg 
ON cde.keywordGroupId = kvg.keywordValueGrpId 
where kvg.[name] = @definitionName 
group by cde.processPath 
order by total desc  

Éditer: Apparemment, les gens continuent à se plaindre de mon utilisation des sous-requêtes. En fait, cela ne fait aucune différence. Je les ai ajoutés juste avant de poster cette question pour qu'il soit plus facile de voir ce qui se passe. Mais ils ont seulement rendu les choses plus confuses, alors je l'ai changé pour ne pas les utiliser.

Modifier: Indices utilisés:

ClientDefinitionEntry: 
IX_ClientDefinitionEntry |nonclustered located on PRIMARY|clientId, keywordGroupId 

KeyWordValueGroups 
IX_KeywordValueGroups  |nonclustered located on PRIMARY|keywordValueGrpId 
IX_KeywordValueGroups_2 |nonclustered located on PRIMARY|version 
IX_KeywordValueGroups_Name |nonclustered located on PRIMARY|name 
+0

Des exemples de données pour ces tables seraient probablement utiles ... –

+0

Quels index avez-vous en place? Sont-ils à jour? –

+0

Je suis tout à fait d'accord avec Andomar et Frederik - faites d'abord une recherche de base avant de vous lancer dans des changements de DB ou de faire des suppositions sur ce qui doit être indexé. De cette façon, vous risquez moins de perdre du temps avec des solutions inappropriées. – Xiaofu

Répondre

2

Je m'assurerais que vous avez les index suivants.

L'ID sur KeywordValueGroups.

Le nom sur KeywordValueGroups.

L'ID sur ClientDefinitionEntry avec un INCLUDE pour le processus process.

CREATE INDEX [IX_ClientDefinitionEntry_Id_ProcessPath] ON [dbo].[ClientDefinitionEntry] ([keywordGroupId] ASC) INCLUDE ([processPath]) ON [PRIMARY] 
CREATE INDEX [IX_KeywordValueGroups_Id] ON [dbo].[KeywordValueGroups] ([keywordValueGrpId] ASC) 
CREATE INDEX [IX_KeywordValueGroups_Name] ON [dbo].[KeywordValueGroups] ([name] ASC) 

Je voudrais également modifier la requête à ce qui suit.

select top 1 
    cde.processPath as 'keywordValue', 
    count(*) as 'total' 
from 
    dbo.ClientDefinitionEntry AS cde 
INNER JOIN 
    dbo.KeywordValueGroups AS kvg 
ON 
    cde.keywordGroupId = kvg.keywordValueGrpId 
where 
    kvg.[name] = @definitionName 
group by 
    processPath 
order by 
    total desc 
+0

L'utilisation de "CREATE INDEX [IX_ClientDefinitionEntry_Id_ProcessPath] ON [dbo]. [ClientDefinitionEntry] ([keywordGroupId] ASC) INCLUDE ([processPath]) ON [PRIMARY]" fait avancer les choses beaucoup plus rapidement. Je me fous de la façon dont cela affecte tout le reste en termes de vitesse, puisque cet article particulier était pourquoi il était lent. – Brian

+1

La raison en est que bien que vous ayez probablement un index sur l'ID, le plan de requête aurait montré qu'il devait ensuite effectuer une recherche sur la table réelle pour trouver la valeur de processPath. Si vous effectuez une requête INCLUDE, elle ajoute effectivement cette valeur à l'index. La taille physique de l'index augmente (votre base de données s'agrandit) mais cela signifie que toutes les données requises sont extraites de l'index sans jamais avoir à toucher la table elle-même. –

+0

Oui, cela ramène des souvenirs de ma classe DB. – Brian

3

Comment le plan d'exécution ne ressemble? En y jetant un coup d'œil, vous apprendrez quelle partie de la requête prend le plus de temps et de ressources.

Avez-vous des index sur les colonnes sur lesquelles vous filtrez? Avez-vous des index sur les colonnes que vous utilisez pour vous joindre? Avez-vous des index sur les colonnes que vous utilisez pour le tri? Une fois que vous avez jeté un oeil à cela, et que la requête est encore lente, vous pouvez regarder comment votre base de données/table est fragmentée (dbcc showcontig), et voir s'il est nécessaire de reconstruire les index.
Il peut être utile d'avoir un plan de maintenance qui reconstruit régulièrement vos index.

3

exécuter la requête avec cette option:

SET SHOWPLAN_TEXT SUR

Et ajouter le résultat à la question.

Vérifiez également si vos statistiques sont à jour:

SELECT 
    object_name = Object_Name(ind.object_id), 
    IndexName = ind.name, 
    StatisticsDate = STATS_DATE(ind.object_id, ind.index_id) 
FROM SYS.INDEXES ind 
order by STATS_DATE(ind.object_id, ind.index_id) desc 

et informations sur les index, les définitions de table et les clés étrangères serait utile.

2

Il n'y a vraiment pas assez d'informations pour être sûr. Si vous rencontrez des problèmes de performance dans cette requête, les tables doivent avoir une quantité de données non triviale et vous devez manquer des index importants.

Les index qui vont définitivement aider dépend profondément de la taille des tables et, dans une moindre mesure, de la distribution des valeurs dans les champs KeywordGroupId et KeywordValueGrpId.

Manquant toute autre information, je dirais que vous voulez vous assurer que dbo.KeywordValueGroups.[name] est indexée, ainsi que dbo.ClientDefinitionEntry.[keywordGroupId].

En raison de la façon dont la requête est écrite, un index sur dbo.KeywordValueGroups.[keywordValueGrpId] seul ne peut pas aider, mais un indice composite sur [name], [keywordValueGrpId] le fera probablement. Si vous avez cet index, vous n'avez pas besoin d'un index dédié sur [name].

Basé sur l'intestin sentiment seul, je pourrais hasarder que l'indice sur [name] est un doit, et que cde.keywordGroupId est probablement importante.Si l'index composite sur [name], [keywordValueGrpId] aiderait, cela dépend du nombre d'enregistrements qui sont là avec le même [nom]. La seule façon de savoir avec certitude est d'ajouter les index et de voir ce qui se passe.

Vous devez également réfléchir à la fréquence d'exécution de cette requête (il est donc important de la rendre rapide) et à la fréquence de modification des données sous-jacentes. En fonction de votre situation particulière, l'augmentation de la vitesse pourrait ne pas justifier le coût supplémentaire de maintenance des indices.

0

Je ne sais pas combien de dossiers nous parlons, mais ceci: ordre par le total desc est sur un sens de la colonne calculée tous les calculs sur chaque ligne devra être fait avant que la commande peut se faire. C'est probablement l'une des choses qui ralentissent, mais je ne vois pas d'issue à ce problème particulier. Pas de problème si vous n'avez que quelques enregistrements après la jointure, mais cela pourrait être le cas s'il y en a beaucoup.

Je me concentrerais d'abord sur l'indexation. Nous oublions souvent que lorsque nous créons des clefs de sécurité, elles ne sont pas automatiquement indexées. Vérifiez si les deux parties de la jointure sont indexées.

Étant donné que vous transmettez une valeur dans un paramètre, vous pouvez également avoir un problème de reniflage de paramètre. Google ceci pour les techniques pour résoudre ce problème.