2009-08-25 17 views
0

SQL Server 2008. J'ai cette très grande requête qui a un coût élevé associé. TOAD a une fonctionnalité optimisation de la requête en elle et la seule modification apportée est la suivante:Optimisation de requête. Pourquoi TOAD a-t-il fait cela?

Avant:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM RCINSP_EXT RIN_EXT 
           INNER JOIN dbo.rcinsp RIN 
            ON RIN_EXT.fkey_id = RIN.identity_column) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno = RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

Après:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
           RIN_EXT.scar, 
           RIN.fcreceiver, 
           RIN.fcitemno 
          FROM dbo.rcinsp RIN 
           INNER JOIN RCINSP_EXT RIN_EXT 
            ON RIN.identity_column = COALESCE (RIN_EXT.fkey_id , RIN_EXT.fkey_id)) RIN1 
     ON RCI.freceiver = RIN1.fcreceiver 
      AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
      AND RCI.fitemno <= RIN1.fcitemno 
WHERE RED.[YEAR] = '2009' 

Le champ est un champ char (3), ce qui est SQL Server 2008.

N'importe quelle idée pourquoi la leur est tellement plus rapide que le mien?

+0

Si vous remarquez, ils ont fait FROM RIN et INNER JOIN RIN_EXT, alors que vous avez fait FROM RIN_EXT et INNER JOIN RIN. Vous ne savez pas si vous avez manqué d'autres différences, vous ne savez pas si vous avez fait des mesures en supprimant la ligne que vous avez commentée et cette ligne particulière est à l'origine de l'amélioration des performances. – JustLoren

+0

La meilleure option consiste à comparer les plans de requête pour les 2 requêtes et voir quels opérateurs ils utilisent. –

+0

Je suis désolé, j'ai réalisé que le premier script manquait le reste des critères de jointure. – DavidStein

Répondre

2

Vous n'avez pas affiché la condition ON dans la requête "Before", donc je ne sais pas ce que TOAD a changé. Cependant, je vais deviner ce qui s'est passé.

L'optimiseur de requêtes SQL Server utilise des estimations de coût pour choisir le plan de requête. Les estimations de coûts sont basées sur les estimations du nombre de lignes. Si les estimations du nombre de lignes ne sont pas exactes, l'optimiseur peut ne pas choisir le meilleur plan.

Certaines estimations de nombre de lignes sont généralement précises, comme celles du formulaire (colonne = valeur) pour une colonne avec des statistiques. Cependant, certaines estimations du nombre de lignes ne peuvent être devinées, comme (colonne = autre colonne) si les colonnes ne sont pas liées par une contrainte de clé étrangère, ou (expression = valeur), où l'expression n'est pas triviale ou implique plus d'une colonne .

Lorsque les statistiques ne guident pas une estimation du nombre de lignes, SQL Server utilise des estimations génériques. Si vous comparez les estimations de nombre de lignes dans un plan estimé aux montants de ligne réels dans un plan réel, vous pouvez parfois voir le problème et "tromper" l'optimiseur en modifiant son estimation de nombre de lignes.

Si vous ajoutez des prédicats avec ET qui ne restreignent pas réellement les résultats, vous pouvez réduire l'estimation du nombre de lignes si l'optimiseur ne peut pas reconnaître qu'ils sont superflus. De même, si vous ajoutez des prédicats avec OR qui ne donnent pas de résultats supplémentaires, vous pouvez augmenter l'estimation du nombre de lignes. Peut-être que l'estimation du nombre de lignes était trop élevée et que les prédicats supplémentaires les corrigent, ce qui se traduit par de meilleures estimations des coûts pour les plans envisagés et un meilleur choix de plan à la fin.

2

Cela ressemble à une chose ascendante de recherche d'index - puisqu'il a ajouté un> = - Nous ne voyons pas assez sur le reste de votre requête, mais évidemment il y a d'autres données sur RCI.fitemno qu'il a pu déduire le reste de votre requête

Il est étrange que ceci:

 AND RCI.fitemno >= RIN1.fcitemno -- ***** RIGHT HERE 
     AND RCI.fitemno <= RIN1.fcitemno 

n'a pas été transformé en ceci:

 AND RCI.fitemno = RIN1.fcitemno 

Comme ils sont équivalents.

2

L'ajout de plus-et-moins-que dans une requête est un vieux truc qui pousse parfois l'optimiseur de requête à utiliser un index sur cette colonne. Donc, cette astuce:

AND RCI.fitemno >= RIN1.fcitemno 
AND RCI.fitemno <= RIN1.fcitemno 

force la base de données à utiliser les index sur les colonnes de Rin1 et RCI si elle est présente. Je ne suis pas sûr si les index temporaires sont créés à la volée lorsque vous faites cela.

J'avais l'habitude de faire ces trucs avec une base de données DB2, et ils ont bien fonctionné.

Questions connexes