web-dev-qa-db-fra.com

Dans quelle mesure les compilations SQL ont-elles un impact sur les performances de SQL Server?

Je suis en train de profiler une instance de SQL Server 2005 et je, via le PerfMon SQLServer:SQL Statistics - SQL Compilations/sec métrique, je vois que la moyenne est d'environ 170 environ.

J'ai supprimé SQL Profiler et recherché les événements SP: Compile ou SQL: Compile. Apparemment, ils n'existent pas. J'ai trouvé Stored Procedure/SP:Recompile et TSQL/SQL:StmtRecompile événements. La quantité de données que je vois dans le profileur suggère que ce sont les mauvais événements à regarder, bien que je ne sois pas sûr.

Alors mes questions. Des réponses à ces questions seraient formidables.

  1. Comment puis-je voir ce qui se compile exactement dans SQL Server?
  2. Ai-je choisi les mauvaises mesures à consulter? Dans Perfmon ou SQL Profiler?
  3. En ce qui concerne Stored Procedure/SP:Recompile et TSQL/SQL:StmtRecompile événements dans SQL Profiler ... ils n'incluent pas la métrique Duration. Comment puis-je évaluer l'impact de ces événements sur le système s'ils ne fournissent aucun moyen de voir l'impact temporel sur le système.
22
AngryHacker

Compilations SQL/sec est une bonne métrique, mais uniquement lorsqu'elle est couplée avec Demandes de lot/sec. En soi, les compilations par seconde ne vous disent pas grand-chose.

Vous voyez 170. Si la demande de lot par seconde n'est que de 200 (un peu exagéré pour l'effet), alors oui, vous devez aller au fond de la cause (très probablement une surutilisation des requêtes ad hoc et des plans à usage unique). Mais si votre demande de lot par seconde mesure environ 5000, 170 compilations par seconde ne sont pas mauvaises du tout. C'est une règle générale que Compilations/sec doit être à 10% ou moins que le total Demandes de lot/sec.

Si vous voulez vraiment explorer ce qui est mis en cache, exécutez la requête suivante qui utilise les DMV appropriés:

select
    db_name(st.dbid) as database_name,
    cp.bucketid,
    cp.usecounts,
    cp.size_in_bytes,
    cp.objtype,
    st.text
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) st

Pour obtenir tous les plans à usage unique (un décompte):

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
)
select count(*)
from PlanCacheCte
where usecounts = 1

Pour obtenir un ratio du nombre de plans de comptage à usage unique que vous avez comparés à tous les plans mis en cache:

declare @single_use_counts int, @multi_use_counts int

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @single_use_counts = count(*)
from PlanCacheCte
where usecounts = 1

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @multi_use_counts = count(*)
from PlanCacheCte
where usecounts > 1

select
    @single_use_counts as single_use_counts,
    @multi_use_counts as multi_use_counts,
    @single_use_counts * 1.0 / (@single_use_counts + @multi_use_counts) * 100
        as percent_single_use_counts

Quant aux durées capturées via une trace SQL Server, elles ne sont pas disponibles pour les événements de recompilation. Il n'est pas si important de voir la durée ou la douleur que la compilation du plan provoque, car il n'y a pas grand-chose à faire pour une situation au cas par cas. La solution consiste à tenter de limiter les compilations et recompilations par la réutilisation des plans (requêtes paramétrées, procédures stockées, etc.).

33
Thomas Stringer

Il existe trois compteurs pertinents qui doivent être enregistrés à l'aide de PerfMon (ou d'une autre solution tierce). Le point clé est d'enregistrer ces statistiques d'une manière ou d'une autre.

  • Statistiques SQL\Demandes de lot/s
  • Statistiques SQL\Compilations SQL/s
  • Statistiques SQL\Recompilations SQL/s

Comme Thomas Stringer l'a mentionné , il est bon de garder un œil sur le ratio de compilations/demande de batch. Évidemment, plus c'est bas, mieux c'est, mais il n'y a que des lignes directrices pour ce qui est "bon", et vous seul pouvez décider ce qui est acceptable. La quantité absolue de gain de perf que vous verrez en réduisant le nombre de compilations dépend de nombreux facteurs.

J'aime aussi regarder le rapport de recompilations/compilation , pour avoir une idée de la quantité de réutilisation du plan de requête. Encore une fois, plus c'est bas, mieux c'est. Dans ce cas, cependant, vous souhaitez que les recompilations se produisent dans le système à mesure que les statistiques changent (si la base de données est en lecture seule et que vous avez des recompilations ... quelque chose peut ne pas fonctionner). Comme je l'ai dit précédemment, il n'y a que des directives pour ce qui est "bon".

Ce que vous voulez vraiment faire, c'est faire évoluer ces chiffres au fil du temps, donc si vous voyez un pic énorme dans l'un ou l'autre des ratios, quelque chose s'est déployé qui n'utilise pas correctement les plans de requête (idéalement, cela est détecté pendant les tests) - utilisez Shark's analyse les requêtes pour trouver les coupables. De plus, en voici une pour trouver des requêtes fréquemment recompilées:

SELECT TOP 50
    qs.plan_generation_num,
    qs.execution_count,
    qs.statement_start_offset,
    qs.statement_end_offset,
    st.text
    FROM sys.dm_exec_query_stats qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
    WHERE qs.plan_generation_num > 1
    ORDER BY qs.plan_generation_num DESC

Si vous enregistrez également des statistiques d'utilisation du processeur, toutes les statistiques peuvent être corrélées ensemble pour savoir à quel point cela fait mal et à quel point vos correctifs vous aident. Dans la pratique, j'ai constaté que même une seule stratégie de plan de requête incorrecte sur un sproc de base peut mettre un serveur à genoux; évidemment YMMV.

10
Jon Seigel