sfondo
Ho una query in esecuzione su SQL Server 2008 R2 che unisce e / o unisce a sinistra circa 12 "tabelle" diverse. Il database è abbastanza grande con molte tabelle di oltre 50 milioni di righe e circa 300 tabelle diverse. È per un'azienda di grandi dimensioni che ha 10 magazzini in tutto il paese. Tutti i magazzini leggono e scrivono nel database. Quindi è piuttosto grande e piuttosto occupato.
La query con cui ho problemi è simile a questa:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
Si noti che uno dei join si trova su una query secondaria non correlata.
Il problema è che a partire da questa mattina, senza alcuna modifica (che io o qualcuno del mio team conosciamo) al sistema, la query che richiede normalmente circa 2 minuti per l'esecuzione, ha iniziato a richiedere un'ora e mezza per l'esecuzione, quando corse a tutti. Il resto del database ronza bene. Ho rimosso questa query dallo sproc in cui di solito viene eseguita e l'ho eseguita in SSMS con variabili di parametro codificate con la stessa lentezza.
La stranezza è che quando prendo la sottoquery non correlata e la butto in una tabella temporanea, e quindi uso quella invece della sotto-query, la query funziona correttamente. Inoltre (e questo è il più strano per me) se aggiungo questo pezzo di codice alla fine della query, la query funziona alla grande:
and t.name like '%'
Ho concluso (forse in modo errato) da questi piccoli esperimenti che la ragione del rallentamento è dovuta alla configurazione del piano di esecuzione memorizzato nella cache di SQL: quando la query è leggermente diversa, deve creare un nuovo piano di esecuzione.
La mia domanda è questa: quando una query che era in esecuzione veloce inizia improvvisamente a funzionare lentamente nel cuore della notte e nient'altro è interessato tranne questa query, come posso risolverla e come posso evitare che accada in futuro ? Come faccio a sapere cosa sta facendo SQL internamente per renderlo così lento (se la query errata viene eseguita, potrei ottenere il suo piano di esecuzione ma non funzionerà - forse il piano di esecuzione previsto mi darebbe qualcosa?)? Se questo problema riguarda il piano di esecuzione, come posso impedire a SQL di pensare che piani di esecuzione davvero scadenti siano una buona idea?
Inoltre, questo non è un problema con lo sniffing dei parametri. L'ho già visto prima, e non è così, dato che anche quando codifico le variabili in SSMS, ottengo comunque prestazioni lente.