TSQL: trova query che causano separatamente troppe compilazioni e ricompilazioni SQL


8

Voglio scoprire cosa sta causando le compilazioni SQL elevate (non le ricompilazioni) che vedo nei contatori di Performance Monitor.

Ecco la mia opinione su questo: se vedo molte compilazioni SQl, significa che le query sul nostro sistema non vengono memorizzate nella cache per i seguenti motivi:

  • Molte domande ad hoc
  • Esecuzione di query che SQl non memorizza nella cache, ad esempio:

    UPDATE table1 SET col1 = 'Stringa più lunga di 8000 caratteri .....' DOVE key_column = some int

  • I piani stanno scadendo e vengono rimossi dalla cache perché: la cache sta esaurendo lo spazio o i piani non vengono utilizzati abbastanza a lungo.

L'unica cosa che si avvicina alla cattura degli inserimenti di cache nel profiler è Stored Procedures-> SP: CacheInserts ma si occupa solo della cache delle stored procedure.

Quindi ho provato quanto segue per ottenere query ad hoc:

SELECT [cp].[refcounts] -- when Refcounts becomes 0, plan is excluded from cache.
    , [cp].[usecounts] 
    , [cp].[objtype] 
    , st.[dbid] 
    , st.[objectid] 
    , st.[text] 
    , [qp].[query_plan] 
FROM sys.dm_exec_cached_plans cp     
CROSS APPLY sys.dm_exec_sql_text ( cp.plan_handle ) st     
CROSS APPLY sys.dm_exec_query_plan ( cp.plan_handle ) qp ;

Ho pensato che le query che causavano le compilazioni dovessero essere quelle con objtype = Adhoc ma questo potrebbe anche riguardare le ricompilazioni. Ora devo eseguire il profiler, acquisire query che causano ricompilazioni e quindi eliminarle dall'elenco precedente.

Sto andando nella giusta direzione?

Esiste una singola query che posso usare per ottenere solo compilazioni SQL senza troppo lavoro?

Risorse che mi hanno aiutato a conseguire le conoscenze di cui sopra:

http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/954b4fba-3774-42e3-86e7-e5172abe0c83 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=143946 http: //technet.microsoft.com/en-nz/library/cc966425(en-us).aspx
http://www.sqlservercentral.com/Forums/Topic914951-360-1.aspx

Qualsiasi aiuto è molto apprezzato.

Risposte:


7

Non penso che tu possa trovarlo in modo semplice, ma è comunque possibile superarlo. Profiler offre molti tipi di classi di eventi che possono essere utilizzati per analizzare le prestazioni di una query. Avvia una nuova sessione di Profiler e controlla i seguenti eventi:

Performance: Performance statistics
Stored Procedures: RPC:Completed
TSQL: SQL:BatchCompleted
TSQL: SQL: BatchStarting

Selezionare Mostra tutte le colonne e selezionare ognuna delle colonne in Prestazioni: solo evento Statistiche sulle prestazioni. Il resto degli eventi può essere lasciato con le impostazioni predefinite.

Quindi, seleziona Filtri di colonna e filtra per DatabaseName e / o LoginName / ApplicationName / HostName ecc., Se li conosci. Lo scopo è quello di limitare il numero di righe distribuite in Profiler e concentrarsi solo sulle tue esigenze.

Quindi, premere Esegui e lasciarlo funzionare per un po '(2-3 minuti tutto il tempo necessario). Analizzare i risultati eliminati osservando principalmente: Evento delle statistiche sulle prestazioni.

Se si verificano spesso statistiche sulle prestazioni, significa che il piano di una query è stato memorizzato nella cache per la prima volta, compilato, ricompilato o eliminato da PlanCache. Dalla mia conoscenza, se una query non ha il suo piano di query in Plan Cache, vedrai 2 righe dell'evento PerformanceStatistics e seguite da SQL: BatchStarting , quindi SQL: BatchCompleted . Significa che il piano di query è stato prima compilato, memorizzato nella cache e quindi la query è stata avviata e completata.

Guarda le seguenti colonne in Evento Statistiche prestazioni:

SPID - ID of the session on which the event occurred. You can use it to identify the       
       row on SQL:BatchCompleted event which will display the SQL Query text and other  
       usefull information (Read/Writes, StartTime/EndTime)
Duration - Total time, in microseconds, spent during compilation.
EventSubClass - 0 = New batch SQL text that is not currently present in the cache.
                1 = Queries within a stored procedure have been compiled.
                2 = Queries within an ad hoc SQL statement have been compiled.
                3 = A cached query has been destroyed and the historical performance         
                    data associated with the plan is about to be destroyed.
                4 = A cached stored procedure has been removed from the cache and the  
                    historical performance data associated with it is about to be 
                    destroyed.

                5 = A cached trigger has been removed from the cache and the historical  
                    performance data associated with it is about to be destroyed.

Considerando il numero EventSubClass puoi scoprire cosa è successo con il piano di query e prendere misure specifiche. Inoltre, è possibile aggiungere altre colonne alle Stored procedure e alle classi di eventi TSQL se si è intercettati in HostName, WindowsUser o altre informazioni dalla traccia di Profiler. Inoltre, la traccia può essere memorizzata in una tabella SQL, rendendo l'analisi più semplice e molto più personalizzabile. Ecco un link che descrive di più la classe di eventi di Performance Statistics.


4

Bene, prima vediamo se c'è pressione sulla cache.

select bpool_visible from sys.dm_os_sys_info
go

Moltiplicare quel numero per 8 per ottenere la memoria in K. 75% di questo da 0-4G + 10% di questo da 4G-64G + 5% di più è il limite di pressione della cache del piano . Se si raggiunge il 75% di questo limite, SQL Server inizierà a eliminare i piani dalla cache. Questa eliminazione si verifica quando un nuovo piano di query viene aggiunto alla cache, quindi quel thread verrà messo in pausa per fare questo lavoro. La seconda cosa che può causare l'eliminazione dei piani è se il numero di piani supera il 4x del numero di bucket hash (una tabella hash associa un plan_handle a un piano). Ce ne sono 10.000 su un sistema a 32 bit e 40.000 su un sistema a 64 bit.

select type, sum(pages_allocated_count) as pages_used from sys.dm_os_memory_objects 
where type in ('MEMOBJ_CACHESTOREOBJCP', 'MEMOBJ_CACHESTORESQLCP', 'MEMOBJ_CACHESTOREXPROC')
group by type
go

La decisione su cosa eliminare non viene presa in base all'uso, ma al costo del piano, i piani più economici vengono eliminati per primi (costo di produzione, non esecuzione). Puoi vederlo se aggiungi le colonne original_coste la current_costtua query su sys.dm_exec_cached_plans. Un piano ad hoc inizia da 0 e viene incrementato di 1 ogni volta che viene utilizzato. Quando si verifica la pressione della cache, SQL Server sottrae la metà da ciascun costo, quindi elimina quelli che hanno raggiunto 0.

Se hai molti SQL ad hoc, prova:

exec sp_reconfigure 'optimize for ad hoc workloads', 1
go
reconfigure
go

In questa modalità, SQL Server memorizza nella cache solo uno "stub" di circa 300 byte (un normale piano di query ha un minimo di 24k), contenente un hash e un puntatore al testo SQL, la prima volta che vede una particolare istruzione SQL, quindi successivamente memorizza nella cache l'intero piano se viene eseguito di nuovo. Ciò non ridurrà necessariamente le compilazioni da solo, ma alleggerirà la pressione della memoria nella cache del piano.

Nota: funziona nel 2008, non provato nel 2005.

Un altro trucco è

alter database ... set parameterization forced
go

Ciò farà sì che SQL Server tratti le costanti come parametri, il che può aiutare con la funzionalità di autoparameterizzazione che di solito memorizza nella cache i piani per istruzioni SQL simili. SQL ad hoc dovrebbe avere i suoi piani di query memorizzati nella cache, a meno che il server non abbia poca memoria, ma questo si basa su corrispondenze testuali esatte a meno che non possa essere parametrizzato, nel qual caso si comporta più come una query preparata.


Grazie! Conoscevo questa opzione di "parametrizzazione forzata" ma avevo paura di usarla. L'unico svantaggio che posso vedere usando questo è che riempirà la cache. Ho ragione?
Manjot

3

Hai molti lavori di SQL Server in esecuzione frequentemente su questa casella? Si noti che nel 2005 le query sui processi degli agenti NON sono memorizzate nella cache e possono causare anche la compilazione della cache e le compilazioni sql.

Guarda il numero di piani con conteggi di riutilizzo bassi. Questi sono i tuoi colpevoli.

Di seguito alcune note correlate sul piano di memorizzazione nella cache.

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat.aspx

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Clearing-the-cache-are-there-other-options.aspx


0

Questo effetto è noto come "inquinamento del piano di query", in cui molte query SQL simili generano piani di esecuzione separati, ma equivalenti.

Le query ad hoc causano un sovraccarico di analisi individuali, ma di solito non interrogano l'inquinamento dei piani, poiché i loro piani non vengono memorizzati. Ciò è diverso per le query con un solo parametro (in MS SQL Server), queste verranno trattate come una query con parametri.

Esistono alcuni casi tipici per l'inquinamento del piano di query:

  • Query SQL con un solo parametro letterale hard coded (come 'select id, name from person where id = 1234')
  • specialmente se usato con comandi / stored procedure che impongono al database di archiviare il piano di query, come 'sp_prepexec' o sp_executesql 'sotto MSSQL (penso che' esegui immediato 'sotto Oracle funziona in modo simile)
  • query parzialmente parametrizzate, con grande varianza nei valori letterali "hard coded", come "select * from SoccerMatches sm where sm.Date>?" e sm.Date <? e HomeClubId = 5678 e GuestClubId = 1234 '. Ciò salverà i piani di query a causa dei parametri, ma creerà un nuovo piano di query per ogni HomeClub o GuestClub modificato (specialmente poiché i valori di data / ora sono un'ottima occasione per introdurre parametri in molte API DB, quando le query falliscono a causa di una data locale diversa i formati).
  • Un'altra fonte di inquinamento del piano di query può essere quadri come ADO.NET con driver insufficienti, in combinazione con valori stringa / (n) varchar. Alcune implementazioni / driver imposteranno le dimensioni dei parametri sulla lunghezza effettiva della stringa, causando un piano di query separato per ogni diversa lunghezza del parametro stringa nella query. La migliore pratica sembra essere l'uso della dimensione massima del campo (ad esempio varchar (4000)) o un driver che mette la lunghezza corretta
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.