Plan d'exécution différent lors de l'exécution directe d'une instruction et à partir d'une procédure stockée

StackOverflow https://stackoverflow.com/questions/421275

Question

Lors du développement d'une nouvelle requête au travail, je l'ai écrite et profilée dans l'Analyseur de requêtes SQL. La requête fonctionnait vraiment bien sans analyse de table, mais lorsque je l'ai encapsulée dans une procédure stockée, les performances étaient horribles. Lorsque j'ai examiné le plan d'exécution, j'ai constaté que SQL Server avait choisi un plan différent qui utilisait une analyse de table au lieu d'une recherche d'index sur TableB (j'ai été forcé de masquer un peu les noms de table et de colonne, mais aucune partie de la logique de requête. a changé).

Voici la requête

SELECT     
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)) AS Day, 
    DATEPART(hh, TableA.Created) AS [Hour], 
    SUM(TableB.Quantity) AS Quantity, 
    SUM(TableB.Amount) AS Amount
FROM
    TableA
    INNER JOIN TableB ON TableA.BID = TableB.ID
WHERE     
    (TableA.ShopId = @ShopId)
GROUP BY 
    DATEADD(dd, 0, DATEDIFF(dd, 0, TableA.Created)), 
    DATEPART(hh, TableA.Created)
ORDER BY 
    DATEPART(hh, TableA.Created)

Lorsque j'exécute la requête " raw " Je reçois les statistiques de suivi suivantes

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   75        41      7      0

Et quand j'exécute la requête en tant que proc stocké en utilisant la commande suivante

DECLARE @ShopId int
SELECT @ShopId = 1
EXEC spStats_GetSalesStatsByHour @ShopId

Je reçois les statistiques de trace suivantes

Event Class         Duration  CPU  Reads Writes
SQL:StmtCompleted   222       10     48      0

J'obtiens également le même résultat si je stocke la requête dans un nvarchar et l'exécute à l'aide de sp_executesql comme ceci (il fonctionne comme le sproc)

DECLARE @SQL nvarchar(2000)
SET @SQL = 'SELECT DATEADD(dd, ...'
exec sp_executesql @SQL

La procédure stockée ne contient rien à l'exception de l'instruction select ci-dessus. Qu'est-ce qui ferait que SQL Server choisisse un plan d'exécution inférieur simplement parce que l'instruction est exécutée en tant que procédure stockée?

Nous utilisons actuellement SQL Server 2000

.
Était-ce utile?

La solution

Cela a généralement quelque chose à voir avec le sniffing de paramètres. Cela peut être très frustrant. Parfois, il peut être résolu en recompilant la procédure stockée, et parfois vous pouvez même utiliser une variable en double dans la procédure stockée comme ceci:

alter procedure p_myproc (@p1 int) as
declare @p1_copy int;
set @p1_copy = @p1;

Ensuite, utilisez @ p1_copy dans la requête. Cela semble ridicule, mais cela fonctionne.

Consultez ma question récente sur le même sujet:

Pourquoi confond-on l'optimiseur SqlServer avec paramètres?

Autres conseils

Oui, je l'avais aussi vu sur Oracle DB 11g. La même requête fonctionnait rapidement sur 2 nœuds du serveur de base de données à l'invite de SQL MAIS lorsqu'elle était appelée depuis un paquet, elle se bloquait littéralement!

a dû effacer le pool partagé pour obtenir un comportement identique: raison de l'exécution d'un travail / script dont l'ancienne copie était verrouillée dans la mémoire cache / mémoire de la bibliothèque sur un nœud avec un plan d'exécution inférieur.

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