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:
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_recompile
a 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_recompile
contro 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;

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.

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.

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.

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

Ottenere le definizioni di tabella e indice
Puoi facilmente fare clic con il tasto destro su SSMS per eseguire lo script delle cose.

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.