J'ai lu d'excellents articles concernant la mise en cache des plans SQL Server par Kimberly Tripp tels que celui-ci: http://www.sqlskills.com/blogs/kimberly/plan-cache-and-optimizing-for-adhoc -charges de travail /
Pourquoi existe-t-il même une option pour "optimiser pour des charges de travail ad hoc"? Cela ne devrait-il pas toujours être activé? Que les développeurs utilisent SQL ad-hoc ou non, pourquoi ne pas activer cette option sur chaque instance qui la prend en charge (SQL 2008+), réduisant ainsi le gonflement du cache?
L'équipe de développement de SQL Server travaille sur le principe de la moindre surprise - donc SQL Server a généralement de nouvelles fonctionnalités désactivées afin de conserver le comportement des versions précédentes.
Oui, l'optimisation pour les charges de travail ad hoc est excellente pour réduire le gonflement du cache du plan - mais testez-le toujours en premier!
[Edit: Kalen Delaney raconte une anecdote intéressante qu'elle a demandé à l'un de ses amis ingénieurs Microsoft s'il y aurait des circonstances où il ne serait pas approprié de l'activer. Il revient plusieurs jours plus tard pour dire - imaginez une application qui a BEAUCOUP de requêtes différentes, et chaque requête s'exécute exactement deux fois au total. Cela pourrait alors être inapproprié. Autant dire qu'il n'y a pas beaucoup d'applications comme ça!]
[Modifier: si la majorité de vos requêtes sont exécutées plus d'une fois (pas exactement deux fois); ce serait probablement inapproprié. La règle générale serait de la désactiver s'il existe de nombreuses requêtes ad hoc à usage unique dans la base de données; cependant, il n'y a pas encore beaucoup d'applications comme ça.]
Vous trouverez ci-dessous un petit code qui vous aidera à décider si la "commutation d'optimisation pour les charges de travail ad hoc ON/OFF" sera bénéfique ou non. Nous vérifions normalement cela dans le cadre de notre bilan de santé pour les serveurs internes et clients.
C'est l'option la plus sûre à activer et est bien décrite par Brad ici et par Glenn Berry ici .
--- for 2008 and up .. Optimize ad-hoc for workload
IF EXISTS (
-- this is for 2008 and up
SELECT 1
FROM sys.configurations
WHERE NAME = 'optimize for ad hoc workloads'
)
BEGIN
DECLARE @AdHocSizeInMB DECIMAL(14, 2)
,@TotalSizeInMB DECIMAL(14, 2)
,@ObjType NVARCHAR(34)
SELECT @AdHocSizeInMB = SUM(CAST((
CASE
WHEN usecounts = 1
AND LOWER(objtype) = 'adhoc'
THEN size_in_bytes
ELSE 0
END
) AS DECIMAL(14, 2))) / 1048576
,@TotalSizeInMB = SUM(CAST(size_in_bytes AS DECIMAL(14, 2))) / 1048576
FROM sys.dm_exec_cached_plans
SELECT 'SQL Server Configuration' AS GROUP_TYPE
,' Total cache plan size (MB): ' + cast(@TotalSizeInMB AS VARCHAR(max)) + '. Current memory occupied by adhoc plans only used once (MB):' + cast(@AdHocSizeInMB AS VARCHAR(max)) + '. Percentage of total cache plan occupied by adhoc plans only used once :' + cast(CAST((@AdHocSizeInMB / @TotalSizeInMB) * 100 AS DECIMAL(14, 2)) AS VARCHAR(max)) + '%' + ' ' AS COMMENTS
,' ' + CASE
WHEN @AdHocSizeInMB > 200
OR ((@AdHocSizeInMB / @TotalSizeInMB) * 100) > 25 -- 200MB or > 25%
THEN 'Switch on Optimize for ad hoc workloads as it will make a significant difference. Ref: http://sqlserverperformance.idera.com/memory/optimize-ad-hoc-workloads-option-sql-server-2008/. http://www.sqlskills.com/blogs/kimberly/post/procedure-cache-and-optimizing-for-adhoc-workloads.aspx'
ELSE 'Setting Optimize for ad hoc workloads will make little difference !!'
END + ' ' AS RECOMMENDATIONS
END
Imaginez un serveur de production qui ne traite que 5 requêtes différentes, mais plusieurs milliers de requêtes par seconde. Vous êtes l'équipe de développement Microsoft SQL Server. Vous allez jouer avec la mise en cache du plan. Activez-vous ce comportement par défaut lorsque vous savez que certains de vos clients les plus importants et les plus critiques (par exemple, la mise en œuvre SAP interne de Microsoft) travaillent sur le même campus et utilisent la même cafétéria que vous?
Lorsque vous activez l'option " Optimiser pour les charges de travail ad hoc", les requêtes ad hoc qui sont exécutées la deuxième fois sont aussi lentes que la première, car vous compilez un plan d'exécution et extraire les mêmes données (sans les mettre en cache) les 2 premières fois.
Ce n'est peut-être pas un gros problème, mais vous le remarquerez lors du test des requêtes.
Alors, que se passe-t-il maintenant, sans cette option est activée et un cache plein de 1-Off Des requêtes ad hoc?
Lorsque cette fonctionnalité d'optimisation a été introduite, l'algorithme de gestion de la mise en cache a également été mis à jour.
L'article de Kimberly Tripp fait également référence à Kalen Delaney's post à propos de ce changement d'algorithme.
Elle l'explique le mieux:
La modification calcule en fait une taille de cache de plan à laquelle SQL Server reconnaît qu'il y a une pression mémoire et il commencera à supprimer des plans du cache. Les plans à supprimer sont les plans bon marché qui n'ont pas été réutilisés, et c'est une BONNE CHOSE.
Cela signifie que ces plans fastidieux seront les premiers à partir lorsque vous aurez besoin de libérer des ressources.
" Pourquoi avons-nous BESOIN d '" Optimiser pour les charges de travail ad hoc "lorsque SQL Server se charge de supprimer les plans inutilisés si nécessaire?"
Ma réponse à cela est, si vous avez régulièrement une tonne de génération dynamique de sql générant des requêtes ad-hoc non paramétrées, alors il est parfaitement logique d'activer cette fonctionnalité.
.
Voici une requête que j'ai écrite pour vous montrer combien de plans ad hoc vous avez actuellement mis en cache et combien d'espace disque ils consomment (les résultats changeront tout au long de la journée - alors testez-le pendant une période de forte charge):
--Great query for making the argument to use "Optimize for Ad Hoc Workloads":
SELECT S.CacheType, S.Avg_Use, S.Avg_Multi_Use,
S.Total_Plan_3orMore_Use, S.Total_Plan_2_Use, S.Total_Plan_1_Use, S.Total_Plan,
CAST( (S.Total_Plan_1_Use * 1.0 / S.Total_Plan) as Decimal(18,2) )[Pct_Plan_1_Use],
S.Total_MB_1_Use, S.Total_MB,
CAST( (S.Total_MB_1_Use * 1.0 / S.Total_MB ) as Decimal(18,2) )[Pct_MB_1_Use]
FROM
(
SELECT CP.objtype[CacheType],
COUNT(*)[Total_Plan],
SUM(CASE WHEN CP.usecounts > 2 THEN 1 ELSE 0 END)[Total_Plan_3orMore_Use],
SUM(CASE WHEN CP.usecounts = 2 THEN 1 ELSE 0 END)[Total_Plan_2_Use],
SUM(CASE WHEN CP.usecounts = 1 THEN 1 ELSE 0 END)[Total_Plan_1_Use],
CAST((SUM(CP.size_in_bytes * 1.0) / 1024 / 1024) as Decimal(12,2) )[Total_MB],
CAST((SUM(CASE WHEN CP.usecounts = 1 THEN (CP.size_in_bytes * 1.0) ELSE 0 END)
/ 1024 / 1024) as Decimal(18,2) )[Total_MB_1_Use],
CAST(AVG(CP.usecounts * 1.0) as Decimal(12,2))[Avg_Use],
CAST(AVG(CASE WHEN CP.usecounts > 1 THEN (CP.usecounts * 1.0)
ELSE NULL END) as Decimal(12,2))[Avg_Multi_Use]
FROM sys.dm_exec_cached_plans as CP
GROUP BY CP.objtype
) AS S
ORDER BY S.CacheType
Je ne vais pas dire, " Quand vous avez X Mo" ou " Si X% de vos Ad Hoc sont à usage unique "pour activer cette fonction.
Cela n'affecte pas les Sprocs, les déclencheurs, les vues ou le SQL paramétré/préparé - seulement les requêtes ad hoc.
Ma recommandation personnelle est de simplement activer dans votre environnement de production, mais envisagez de le laisser dans votre environnement de développement.
Je dis ceci seulement pour Dev, car si vous optimisez une requête qui prend une minute ou plus à s'exécuter, vous ne voulez pas l'exécuter 3 fois avant vous pouvez voir à quelle vitesse il ira avec le cache - chaque à chaque fois que vous le modifiez pour trouver le meilleur conception d'optimisation.
Si votre travail ne consiste pas à faire cela toute la journée, alors devenez fou et demandez à votre DBA de l'allumer partout.
"Pourquoi ne devrais-je PAS utiliser ...." Au cours de certaines enquêtes sur les performances, il peut être très utile d'extraire des plans du cache de plan en temps réel, tout en observant l'utilisation des ressources. "Optimiser pour les charges de travail ad hoc" peut perturber cela, car les plans de stub adhoc ne renverront pas de plan lors de l'interrogation du cache. Dans un cas comme celui-ci, si la requête et le plan ne peuvent pas être identifiés autrement, le paramètre peut être désactivé et réactivé à des fins d'enquête. Notez qu'un changement dans la définition des requêtes d'effets compilés à partir de ce point. De plus, chaque fois que vous modifiez une propriété "serveur", vérifiez une instance nonprod dans la même version pour vérifier si la modification videra ou non le cache du plan. Personnellement, je déteste être surpris par cela. (Par exemple, la modification de maxdop au niveau du serveur vide généralement le cache du plan, contrairement à la modification de dop dans Resource Governor.)
"Le talon de plan compilé n'a pas de plan d'exécution associé et la requête pour le descripteur de plan ne renverra pas de plan XML." http://technet.Microsoft.com/en-us/library/cc645587.aspx