La maggior parte dei piani di query è stata ricreata nelle ultime 4 ore


9

Ho un problema con le prestazioni del mio database SQL Server. Ho trovato questo strumento sp_BlitzCache . Dopo l'esecuzione del comando, ho ottenuto questa affermazione:

Hai il 92,00% di piani creati nelle ultime 24 ore e il 92,00% creato nelle ultime 4 ore.

Mentre ho identificato il problema (utilizzando SQL Server Profiler, ho verificato le occorrenze di eventi StmtRecompile), sono stato in grado di trovare solo alcune query di ricerca full-text che vengono spesso ricostruite. Tuttavia, le query di ricerca full-text rappresentano solo circa il 5% di tutte le query.

Hai qualche suggerimento su cosa potrebbe causare la ricreazione dei restanti piani dell'87%?

Ho SQL Server 2012 (versione 11.0.6567.0).

Modifica: ho aggiunto i miei contatori delle prestazioni

+---------------------------+--------------------------------+--------------+
|        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 |
+---------------------------+--------------------------------+--------------+

Forse qualcuno ha eseguito DBCC FREEPROCCACHE? : P
Daniel Björk,

@ DanielBjörk Sono l'unica persona che ha il permesso di fare cose come questa, quindi non penso che sia la ragione. Tuttavia, lo controllerò.
Marcin Topolewski,

Stai utilizzando query parametrizzate o stored procedure? o il problema è che hai letterali stringa / numero nel tuo SQL e quindi i piani non possono essere riutilizzati?
James Z,

@JamesZ Sì, sto usando molte query parametrizzate. Lo strumento che ho citato nel mio post, BlitzCache, dice che ho un problema con lo sniffing dei parametri.
Marcin Topolewski,

1
Ricostruisci gli indici o aggiorni le statistiche di notte? Forse c'è una pressione della memoria sul server?
Erik Darling,

Risposte:


6

La query utilizzata per verificare i tempi di creazione del piano è questa

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) ;

anche l'SP fornisce alcuni indizi su dove iniziare le tue ulteriori ricerche

Se queste percentuali sono elevate, potrebbe essere un segno di pressione della memoria o pianificare l'instabilità della cache

A parte gli indizi precedenti, controlla se il tuo server è stato riavviato.

se il tuo server non viene riavviato, di seguito è l'approccio che seguirei

  • controlla se la pressione della memoria di fronte

Per prima cosa, se le impostazioni della memoria sono configurate in modo ottimale. In tal caso, è possibile utilizzare i contatori di seguito per vedere se si è confrontati con la pressione della memoria

Memoria:
Buffer SQL MB disponibile: Buffer SQL di pagine libere
:
Buffer SQL di durata della pagina : Scritte pigre

se si sta affrontando la pressione della memoria, è possibile visualizzare e ottimizzare le query che utilizzano più memoria o provare ad aggiungere più memoria

potresti aver eseguito query che causano la ricompilazione. Alcune includono

  • Modifiche apportate a una tabella o vista a cui fa riferimento la query (ALTER TABLE e ALTER VIEW).

  • Modifiche apportate a una singola procedura, che eliminerebbe tutti i piani per quella procedura dalla cache (ALTER PROCEDURE).

  • Modifiche a tutti gli indici utilizzati dal piano di esecuzione

  • Aggiornamenti sulle statistiche utilizzate dal piano di esecuzione, generati esplicitamente da un'istruzione, come UPDATE STATISTICS, o generati automaticamente.

  • Eliminazione di un indice utilizzato dal piano di esecuzione.

è inoltre possibile consultare questo white paper per ulteriori dettagli sulla memorizzazione nella cache del piano

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


Ho aggiunto i miei contatori delle prestazioni, potresti aiutarmi a interpretare questi valori?
Marcin Topolewski,

puoi trovare contatori dettagliati relativi alla memoria qui: blogs.msdn.microsoft.com/teekamg/2007/11/06/…
TheGameiswar

@TheGameiswar dici "potresti aver eseguito query che causano la ricompilazione ... come modifiche all'indice, aggiornamento sulle statistiche". Se eseguo il reorg / ricostruzione dell'indice in base alla frammentazione + aggiorno le statistiche ogni notte, significa che i miei piani saranno tutti (o quasi) ricreati ogni giorno? è un problema?
Danielle Paquette-Harvey,

2

Per aggiungere ciò che ha detto @TheGameiswar, puoi anche eseguire questa query per vedere i dettagli dei piani che non sono ottenuti dalla 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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.