2010-05-07 6 views
3

J'ai une procédure stockée sur une base de données occupée qui sort constamment haut dans la liste des requêtes coûteuses (d'une certaine manière). La requête est très simple, elle prend un seul paramètre (@ID, int) qui est la clé primaire de la table, et sélectionne l'enregistrement qui correspond à cet ID. La clé primaire est un champ d'identité avec un index clusterisé, donc je suis perplexe quant à la façon d'optimiser cela plus loin?Sql Server requête de requête

La requête est la suivante

CREATE PROCEDURE [dbo].[P_Call_Get] 

    @ID int = null 

AS 

    select ID, 
     AppID, 
     AgentID, 
     AgentLogin, 
     Ext, 
     VDN, 
     VDNName, 
     Skill, 
     SkillName, 
     CallFrom, 
     TelNoFrom, 
     ParentCallID, 
     CallStart, 
     ACWStart, 
     CallEnd, 
     Outcome, 
     StageID, 
     TxTo, 
     TxSuccess, 
     ServiceID, 
     DiallerID, 
     CRC, 
     TSCallID, 
     CallDirection, 
     [Manual], 
     CallBackAgent, 
     CallBackDateTime, 
     Notes 
    from P_Call 
    where (ID = @ID or @ID is null) 

Je ne sais pas la meilleure façon d'afficher le plan d'exécution - tout ce qu'il montre est que 100% de l'opération est repris par l'index cluster scan

+1

Pourriez-vous poster le code? –

+1

Pouvez-vous publier la requête et le plan d'exécution? –

+1

quand vous dites que c'était le plus cher, combien lisait-il? À quelle fréquence est-ce appelé? –

Répondre

8

Je pense qu'en utilisant where (ID = @ID or @ID is null) vous obtenez un plan sous optimal. Divisez ceci en 2 requêtes séparées de sorte que dans le cas où @Id n'est pas nul, il le recherchera directement et vous obtiendrez une recherche plutôt qu'une analyse apparaissant dans le plan. Vous pourriez peut-être créer une vue avec les colonnes dont vous avez besoin pour éviter la répétition (ie de la requête sans clause where)

select ID, 
    AppID, 
    AgentID, 
    AgentLogin, 
    Ext, 
    VDN, 
    VDNName, 
    Skill, 
    SkillName, 
    CallFrom, 
    TelNoFrom, 
    ParentCallID, 
    CallStart, 
    ACWStart, 
    CallEnd, 
    Outcome, 
    StageID, 
    TxTo, 
    TxSuccess, 
    ServiceID, 
    DiallerID, 
    CRC, 
    TSCallID, 
    CallDirection, 
    [Manual], 
    CallBackAgent, 
    CallBackDateTime, 
    Notes 
from P_Call 
+0

Oui, c'est exactement ça. +1 – Quassnoi

+0

Le fractionnement en deux requêtes a fait exactement cela - j'ai maintenant une recherche plutôt qu'une analyse dans mon plan d'exécution. Ce qui m'effraie un peu car j'ai utilisé cette approche dans un certain nombre de SP qui recherchent un certain nombre de critères optionnels. Je voulais poser une question sur une meilleure approche, mais je pense que l'optimisation de ceux-ci est une question distincte – Macros

+0

Je ne suis pas sûr s'il y a un moyen de contourner l'approche de séparation en 2 requêtes. Cela peut être un peu pénible de garder des requêtes complexes synchronisées, surtout si vous utilisez cette approche pour plusieurs paramètres dans la requête. –

0

peut vous utilisez la partition de table. il peut résoudre le problème.

1

Essayez de nettoyer le cache procédure et des tampons mémoire:

DBCC DROPCLEANBUFFERS 
DBCC FREEPROCCACHE 

Ce faisant, avant tester les performances de votre procédure empêchera l'utilisation des plans d'exécution mis en cache et du cache des résultats précédents.

0

Combien de lignes y a-t-il dans la table? Vous réalisez qu'un "scan d'index en cluster" = analyse de table complète.

+0

Je n'ai pas ... mais fais maintenant! ont passé les 2 derniers jours à optimiser les SP basés sur ce – Macros

+0

Bonne affaire. Vous avez probablement déjà compris pourquoi mais j'aurais dû expliquer pourquoi l'optimiseur sélectionnait un plan sous-optimal. La raison pour laquelle l'index ne peut pas être utilisé est la partie (ou @ID est nulle) de la clause WHERE. Les valeurs NULL ne sont pas indexées. –