La plupart des plans de requête ont été recréés au cours des 4 dernières heures

9

J'ai un problème avec les performances de ma base de données SQL Server. J'ai trouvé cet outil sp_BlitzCache . Après l'exécution de la commande, j'ai obtenu cette déclaration:

Vous avez créé 92,00% de plans au cours des dernières 24 heures et 92,00% créés au cours des 4 dernières heures.

Bien que j'aie identifié le problème (à l'aide de SQL Server Profiler, j'ai vérifié les occurrences d'événements StmtRecompile), je n'ai pu trouver que quelques requêtes de recherche en texte intégral qui sont souvent reconstruites. Cependant, les requêtes de recherche en texte intégral représentent environ 5% de toutes les requêtes.

Avez-vous des suggestions sur ce qui pourrait provoquer la recréation des 87% restants?

J'ai obtenu SQL Server 2012 (version 11.0.6567.0).

Edit: j'ai ajouté mes compteurs de performance

+---------------------------+--------------------------------+--------------+
|        object_name        |          counter_name          |  cntr_value  |
+---------------------------+--------------------------------+--------------+
| SQLServer:Buffer Manager  | Background writer pages/sec    |            0 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio         |        28436 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio base    |        28436 |
| SQLServer:Buffer Manager  | Checkpoint pages/sec           |      8259452 |
| SQLServer:Buffer Manager  | Database pages                 |      4434337 |
| SQLServer:Buffer Manager  | Free list stalls/sec           |            9 |
| SQLServer:Buffer Manager  | Integral Controller Slope      |            0 |
| SQLServer:Buffer Manager  | Lazy writes/sec                |         5608 |
| SQLServer:Buffer Manager  | Page life expectancy           |       438901 |
| SQLServer:Buffer Manager  | Page lookups/sec               | 122694703703 |
| SQLServer:Buffer Manager  | Page reads/sec                 |     60994608 |
| SQLServer:Buffer Manager  | Page writes/sec                |    126076564 |
| SQLServer:Buffer Manager  | Readahead pages/sec            |     45305420 |
| SQLServer:Buffer Manager  | Target pages                   |    130990080 |
| SQLServer:Buffer Node     | Database pages                 |      4434337 |
| SQLServer:Buffer Node     | Page life expectancy           |       438901 |
| SQLServer:Buffer Node     | Local node page lookups/sec    |            0 |
| SQLServer:Buffer Node     | Remote node page lookups/sec   |            0 |
| SQLServer:Memory Manager  | External benefit of memory     |            0 |
| SQLServer:Memory Manager  | Connection Memory (KB)         |         3304 |
| SQLServer:Memory Manager  | Database Cache Memory (KB)     |     35474784 |
| SQLServer:Memory Manager  | Free Memory (KB)               |     13229808 |
| SQLServer:Memory Manager  | Granted Workspace Memory (KB)  |            0 |
| SQLServer:Memory Manager  | Lock Memory (KB)               |       455928 |
| SQLServer:Memory Manager  | Lock Blocks Allocated          |      1798154 |
| SQLServer:Memory Manager  | Lock Owner Blocks Allocated    |      3568588 |
| SQLServer:Memory Manager  | Lock Blocks                    |        10562 |
| SQLServer:Memory Manager  | Lock Owner Blocks              |        10617 |
| SQLServer:Memory Manager  | Maximum Workspace Memory (KB)  |     43368000 |
| SQLServer:Memory Manager  | Memory Grants Outstanding      |            0 |
| SQLServer:Memory Manager  | Memory Grants Pending          |            0 |
| SQLServer:Memory Manager  | Optimizer Memory (KB)          |         1400 |
| SQLServer:Memory Manager  | Reserved Server Memory (KB)    |            0 |
| SQLServer:Memory Manager  | SQL Cache Memory (KB)          |       229112 |
| SQLServer:Memory Manager  | Stolen Server Memory (KB)      |      8063232 |
| SQLServer:Memory Manager  | Log Pool Memory (KB)           |         4192 |
| SQLServer:Memory Manager  | Target Server Memory (KB)      |     56934400 |
| SQLServer:Memory Manager  | Total Server Memory (KB)       |     56767824 |
| SQLServer:Memory Node     | Database Node Memory (KB)      |     35474784 |
| SQLServer:Memory Node     | Free Node Memory (KB)          |     13229808 |
| SQLServer:Memory Node     | Foreign Node Memory (KB)       |            0 |
| SQLServer:Memory Node     | Stolen Node Memory (KB)        |      8063208 |
| SQLServer:Memory Node     | Target Node Memory (KB)        |     56934376 |
| SQLServer:Memory Node     | Total Node Memory (KB)         |     56767800 |
+---------------------------+--------------------------------+--------------+
Marcin Topolewski
la source
Peut-être que quelqu'un a exécuté DBCC FREEPROCCACHE? : P
Daniel Björk
@ DanielBjörk Je suis la seule personne qui a la permission de faire des choses comme ça, donc je ne pense pas que ce soit la raison. Cependant, je vais le vérifier.
Marcin Topolewski
Utilisez-vous des requêtes paramétrées ou des procédures stockées? ou est le problème que vous avez des littéraux chaîne / nombre dans votre SQL, et donc les plans ne peuvent pas être réutilisés?
James Z
@JamesZ Oui, j'utilise beaucoup de requêtes paramétrées. L'outil que j'ai mentionné dans mon article, BlitzCache, dit que j'ai un problème avec le reniflage de paramètres.
Marcin Topolewski
1
Reconstruisez-vous des index ou mettez-vous à jour les statistiques tous les soirs? Peut-être qu'il y a une pression mémoire sur le serveur?
Erik Darling

Réponses:

6

La requête utilisée pour tester l'heure de création du plan est la suivante

WITH x AS (
SELECT SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 24 THEN 1 ELSE 0 END) AS [plans_24],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 4 THEN 1 ELSE 0 END) AS [plans_4],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 1 THEN 1 ELSE 0 END) AS [plans_1],
       COUNT(deqs.creation_time) AS [total_plans]
FROM sys.dm_exec_query_stats AS deqs
)
SELECT CONVERT(DECIMAL(3,2), NULLIF(x.plans_24, 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_24],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_4 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_4],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_1 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_1],
       @@SPID AS SPID
INTO #plan_creation
FROM x
OPTION (RECOMPILE) ;

le SP fournit également des indices sur où commencer vos recherches futures

Si ces pourcentages sont élevés, cela peut être un signe de pression mémoire ou de planifier l'instabilité du cache

Autre que les indices ci-dessus, vérifiez si votre serveur a été redémarré.

si votre serveur n'est pas redémarré, voici l'approche que je prendrais

  • vérifier si votre pression sur la mémoire face

Tout d'abord, voyez si vos paramètres de mémoire sont configurés de manière optimale. Si c'est le cas, vous pouvez utiliser les compteurs ci-dessous pour voir si vous êtes confronté à une pression de mémoire

Mémoire: Mo disponible
Buffer SQL: Pages libres
Tampon SQL: Page Life
Tampon SQL: Écritures paresseuses

si vous êtes confronté à une pression sur la mémoire, vous pouvez voir et régler les requêtes qui utilisent plus de mémoire ou essayez d'ajouter plus de mémoire

vous avez peut-être exécuté des requêtes qui provoquent une recompilation .

  • Modifications apportées à une table ou à une vue référencée par la requête (ALTER TABLE et ALTER VIEW).

  • Modifications apportées à une seule procédure, ce qui supprimerait tous les plans de cette procédure du cache (ALTER PROCEDURE).

  • Modifications de tous les index utilisés par le plan d'exécution

  • Mises à jour des statistiques utilisées par le plan d'exécution, générées soit explicitement à partir d'une instruction, comme UPDATE STATISTICS, soit générées automatiquement.

  • Suppression d'un index utilisé par le plan d'exécution.

vous pouvez également consulter ce livre blanc pour plus de détails sur la mise en cache du plan

https://technet.microsoft.com/en-us/library/ee343986(v=sql.100).aspx

TheGameiswar
la source
J'ai ajouté mes compteurs de performance, pourriez-vous m'aider à interpréter ces valeurs?
Marcin Topolewski
vous pouvez consulter les compteurs détaillés liés à la mémoire ici: blogs.msdn.microsoft.com/teekamg/2007/11/06/…
TheGameiswar
@TheGameiswar vous dites "vous avez peut-être exécuté des requêtes qui provoquent une recompilation ... telles que des modifications d'index, une mise à jour des statistiques". Si je réorganise / reconstruit les index en fonction des statistiques de fragmentation + mise à jour tous les soirs, cela signifie-t-il que mes plans seront tous (ou presque) recréés tous les jours? est-ce un problème?
Danielle Paquette-Harvey
2

Pour ajouter ce que @TheGameiswar a dit, vous pouvez également exécuter cette requête pour voir les détails des plans qui ne sont pas obtenus à partir du cache.

;with
    xmlnamespaces (N'http://schemas.microsoft.com/sqlserver/2004/07/showplan' as DYN)
select
    db_name(st.dbid) as DBName
    , object_schema_name(st.objectid, st.dbid) as SchemaName
    , object_name(st.objectid, st.dbid) as ObjectName
    , ecp.objtype
    , st.text
    , qp.query_plan.value('(/DYN:ShowPlanXML/DYN:BatchSequence/DYN:Batch/DYN:Statements/DYN:StmtSimple/@RetrievedFromCache)[1]', 'varchar(100)') as RetrievedFromCache
    , qp.query_plan
into #temp
from sys.dm_exec_cached_plans ecp
    outer apply sys.dm_exec_query_plan(ecp.plan_handle) qp
    outer apply sys.dm_exec_sql_text(ecp.plan_handle) st

select
    *
from #temp t
where t.RetrievedFromCache is null
    and t.DBName is not null
order by t.DBName, t.SchemaName, t.ObjectName;
Dean Savović
la source