Perché la mia domanda è improvvisamente più lenta di ieri?


76

[Saluti]

(controlla uno)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

Ho un (controlla tutto quello che si applica)

[ ] query [ ] stored procedure [ ] database thing maybe  

che funzionava bene (se applicabile)

[ ] yesterday [ ] in recent memory [ ] at some point 

ma è improvvisamente più lento ora.

Ho già verificato per assicurarsi che non sia bloccato e che non sia vittima di attività di manutenzione, report o altri processi fuori banda a lungo in esecuzione.

Qual è il problema, cosa devo fare e quali informazioni posso fornire per ottenere un aiuto?

[*Insert appropriate closing remarks*]

Risposte:


88

Caro [il tuo nome qui]!

Oh no, mi dispiace sentirlo! Cominciamo con alcune nozioni di base per sistemarti in un batter d'occhio.

La cosa in cui ti imbatti si chiama Parameter Sniffing

È una via d'uscita per uno strano problema. Il nome esce dalla lingua. Come la parola tedesca per scoiattolo.

E di solito è tuo amico.

Quando una query colpisce il server, è necessario compilare un piano. Per risparmiare tempo e risorse in un secondo momento, un piano di esecuzione viene memorizzato nella cache in base alle righe stimate che il parametro farà elaborare e restituire il codice.

Il modo più semplice per immaginare che ciò vada male è immaginare una procedura memorizzata che deve contare le cose da due popolazioni sbilenco.

Per esempio:

  • Le persone che indossano magliette CrossFit che non sono infortunate: Zero

  • Le persone che indossano magliette CrossFit che sussultano quando trasaliscono: Tutti

Ovviamente, un'esecuzione di quel codice dovrebbe fare molto più lavoro di un'altra, e i piani di query che vorresti fare quantità completamente diverse di lavoro sembrerebbero totalmente diversi.

Cosa mi oppongo?

Questo è un problema veramente difficile da trovare, testare e risolvere.

  • È difficile da trovare perché non accade in modo coerente
  • È difficile testare perché è necessario sapere quali parametri causano piani diversi
  • È difficile da risolvere perché a volte richiede l'ottimizzazione di query e indice
  • È difficile da risolvere perché potresti non essere in grado di modificare query o indici
  • È difficile da risolvere perché anche se si modificano query o indici, potrebbe comunque tornare

Soluzioni veloci

A volte, tutto ciò che serve è un po 'di chiarezza. O meglio, la tua cache del piano lo fa.

Se è una procedura memorizzata

Prova a correre EXEC sys.sp_recompile @objname = N'schema.procname'. Ciò farà sì che la procedura ricompili un nuovo piano alla successiva esecuzione.

Cosa non risolverà:

  • Processi attualmente in esecuzione.

Ciò che questo non garantisce:

  • Il prossimo processo che verrà eseguito dopo la ricompilazione utilizzerà un parametro che ti darà un buon piano.

Puoi anche puntare sp_recompilea una tabella o a una vista, ma tieni presente che tutto il codice che tocca quella tabella o vista verrà ricompilato. Ciò potrebbe rendere il problema molto più difficile.

Se è una query con parametri

Il tuo lavoro è un po 'più difficile. Dovrai rintracciare l'handle SQL. Non vuoi liberare l'intera cache del piano - proprio come usando sp_recompilecontro un tavolo o una vista, potresti innescare (ah ah ah) tutta una serie di conseguenze indesiderate.

Il modo più semplice per capire questo comando è eseguire sp_BlitzWho *! C'è una colonna chiamata "correzione parametri sniffing" che ha un comando per rimuovere un singolo piano dalla cache. Questo ha gli stessi inconvenienti della ricompilazione, però.

Cosa non risolverà:

  • Processi attualmente in esecuzione.

Ciò che questo non garantisce:

  • Il prossimo processo che verrà eseguito dopo la ricompilazione utilizzerà un parametro che ti darà un buon piano.

Ho ancora bisogno di aiuto!

Avremo bisogno delle seguenti cose:

  • Il buon piano di query, se possibile
  • Il piano di query errato
  • I parametri utilizzati
  • La query in questione
  • Definizioni di tabella e indice

Ottenere i piani di query e query

Se la query è in esecuzione, è possibile utilizzare sp_BlitzWho * o sp_WhoIsActive per acquisire query attualmente in esecuzione.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

NOCCIOLINE

Se la query non è attualmente in esecuzione, è possibile verificarla nella cache del piano, utilizzando sp_BlitzCache *.

Se utilizzi SQL Server 2016+ e hai attivato Query Store, puoi utilizzare sp_BlitzQueryStore *.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Questi ti aiuteranno a rintracciare le versioni memorizzate nella cache della tua Stored Procedure. Se è solo un codice parametrizzato, la tua ricerca è un po 'più difficile. Questo può aiutare, tuttavia:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Dovresti vedere un output abbastanza simile da uno di questi. Ancora una volta, il piano di query che invita alla fredda colonna clicky blu è tuo amico.

NOCCIOLINE

Il modo più semplice per condividere i piani è utilizzare Incolla il piano * o scaricare l'XML in pastebin. Per farlo, fai clic su una di quelle invitanti colonne clicky blu. Il piano di query dovrebbe essere visualizzato in una nuova scheda SSMS.

NOCCIOLINE

Se sei sensibile alla condivisione del codice e della query della tua azienda, puoi utilizzare lo strumento gratuito Plan Explorer di Sentry One per rendere anonimo il tuo piano. Tieni presente che ciò rende più difficile ottenere assistenza: il codice anonimo è molto più difficile da leggere e capire.

Tutti questi strumenti di cui abbiamo parlato dovrebbero restituire il testo della query. Non devi fare nient'altro qui.

Ottenere i parametri è un po 'più difficile. Se stai utilizzando Plan Explorer , c'è una scheda in basso che li elenca tutti per te.

NOCCIOLINE

Se stai usando sp_BlitzCache *, c'è una colonna cliccabile che ti dà la dichiarazione di esecuzione per le procedure memorizzate.

NOCCIOLINE

Ottenere le definizioni di tabella e indice

Puoi facilmente fare clic con il tasto destro su SSMS per eseguire lo script delle cose.

NOCCIOLINE

Se vuoi ottenere tutto in un colpo solo, sp_BlitzIndex * può aiutarti se lo punti direttamente a un tavolo.

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

Questo ti darà la definizione della tabella (anche se non come un'istruzione create) e creerà istruzioni per tutti i tuoi indici.

La raccolta e l'aggiunta di queste informazioni alla tua domanda dovrebbe consentire alle persone di disporre di informazioni sufficienti per aiutarti o indirizzarti nella giusta direzione.

Voglio farlo da solo!

Bene, fico. Sono felice per te. Pazzo.

Esistono molti modi in cui le persone pensano di "correggere" lo sniffing dei parametri:

Ma questi disabilitano davvero lo sniffing dei parametri in diversi modi. Questo non vuol dire che non possono risolvere il problema, non riescono davvero a raggiungere la causa principale.

Questo perché arrivare alla causa principale di solito è piuttosto difficile. Devi cercare quei fastidiosi "problemi di qualità del piano".

A partire dai piani veloce vs lento, cerca differenze come:

  • Indici utilizzati
  • Unisciti all'ordine
  • Seriale vs Parallelo

Cerca anche diversi operatori che rendono il tuo codice sensibile allo sniffing dei parametri:

  • Ricerche
  • Sorts
  • Unisci tipo
  • Concessioni di memoria (e per estensione, sversamenti)
  • bobine

Non lasciarti coinvolgere troppo dalla ricerca vs scan, dalla frammentazione dell'indice o da qualsivoglia delle cose di culto del carico che le persone orlano e guardano intorno.

Di solito, c'è un problema di indicizzazione piuttosto semplice. A volte il codice necessita di una piccola riscrittura.

Se vuoi saperne di più sullo sniffing dei parametri:

Se stai leggendo questo e pensi che mi sia perso un link o uno strumento utile, lascia un commento. Farò del mio meglio per tenerlo aggiornato.



28

Lo sniffing dei parametri non è la sola causa possibile delle prestazioni variabili di una query. Uno dei seguenti motivi comuni può mostrare gli stessi sintomi:

  1. La distribuzione / volume dei dati è cambiato, attraversando un punto di non ritorno decisionale dell'albero di ricerca dell'ottimizzatore
  2. Gli indici / file sono stati frammentati
  3. Le statistiche sono state aggiornate / aggiunte / eliminate o sono diventate obsolete e fuorvianti a causa della modifica dei dati
  4. L'utilizzo della memoria di Windows è cambiato
  5. I registri delle transazioni sono pieni e non troncati, causando ripetute espansioni fisiche dei file
  6. Schema modificato: indice / vista indicizzata / colonna / vincolo aggiunti, modificati o eliminati, tipo di dati modificato, ecc.
  7. Impostazioni flag di traccia modificate
  8. È stato applicato l'aggiornamento di Windows
  9. Impostazione del database o del server modificata
  10. Livello CU server è cambiato
  11. Le impostazioni della sessione dell'applicazione client sono state modificate

Gli articoli 6 - 11 in questo elenco possono accadere solo dopo che sono state intraprese alcune azioni esplicite. Immagino volessi escludere quelli, ma molte volte chi sta vivendo la sfida, non è a conoscenza del fatto che qualcun altro ha apportato modifiche e vale la pena controllarlo prima di intraprendere il percorso di svuotamento delle voci della cache del piano.


1
Grazie per la modifica Paul. @sp_BlitzErik - Non era mia intenzione fornire consigli su argomenti specifici, solo per aumentare la consapevolezza che esistono e potrebbe valere la pena verificarli. Questo non intende in alcun modo diminuire dal tuo ottimo post. Hai trattato il parametro sniffing in modo approfondito, professionale e con buon umore. Mi è piaciuto leggerlo. Voglio solo assicurarmi che se qualcuno qui visita questo post, seguendo il titolo accattivante, viene reso consapevole delle potenziali cause alternative. IMHO aggiunge valore al tuo post, ma se desideri che lo elimini, fammi sapere.
SQLRaptor

No, per niente. Non chiederei mai a qualcuno di cancellare una risposta che non sia errata o dannosa. Penso ancora che potresti aggiungere qualche dettaglio, ma alla fine dipende da te.
Erik Darling,

10

Solo per aggiungere alle risposte esistenti nel caso in cui non aiutassero, quando "improvvisamente" le tue domande si comportano diversamente il giorno successivo, controlla:

  • Lo schema per le tabelle utilizzate è cambiato dall'ultima volta? Nel caso di SSMS, è possibile fare clic con il pulsante destro del mouse sul server in Esplora oggetti e scegliere Reports → Standard Reports → Schema Changes History.
  • Il conteggio degli articoli è aumentato notevolmente? Forse la tua query è molto più lenta quando ci sono molti dati nelle tabelle utilizzate.
  • Qualcun altro sta utilizzando il database contemporaneamente a te? Forse scegli intervalli di tempo in cui non interferisci con il lavoro dell'altro.
  • Come stanno le statistiche di sistema? Forse il server si sta surriscaldando e sta rallentando la CPU o i dischi rigidi stanno esaurendo lo spazio o lo scambio. Forse c'è un altro problema hardware come un incendio o un'alluvione nella stanza del server.

7

Un'altra possibilità è che il team dell'infrastruttura stia utilizzando strumenti come vMotion su VMware e la VM che supporta la tua istanza SQL viene spostata senza problemi da host a host senza che il DBA ne sia a conoscenza.

Questo è un vero problema quando la tua infrastruttura è in outsourcing ... Sto vivendo un vero incubo.

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.