tło
Mam zapytanie działające przeciwko SQL Server 2008 R2, które łączy i / lub dołącza do lewej około 12 różnych „tabel”. Baza danych jest dość duża, z wieloma tabelami ponad 50 milionów wierszy i około 300 różnymi tabelami. To dla dużej firmy, która ma 10 magazynów w całym kraju. Wszystkie magazyny czytają i zapisują dane w bazie danych. Jest więc dość duży i dość zajęty.
Zapytanie, z którym mam problem, wygląda mniej więcej tak:
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
Zauważ, że jedno ze złączeń dotyczy nieskorelowanego zapytania podrzędnego.
Problem polega na tym, że od dzisiejszego ranka, bez żadnych zmian (o których ja lub ktokolwiek z mojego zespołu wie), w systemie, zapytanie, które zwykle trwa około 2 minut, zaczęło zajmować półtorej godziny - w ogóle pobiegł. Reszta bazy danych wciąż nuci. Wyciągnąłem to zapytanie ze sproca, w którym zwykle działa, i uruchomiłem je w SSMS z zakodowanymi na stałe zmiennymi parametrycznymi z tą samą powolnością.
Dziwność polega na tym, że kiedy biorę nieskorelowane pod-zapytanie i wrzucam je do tabeli tymczasowej, a następnie używam tego zamiast pod-zapytania, zapytanie działa poprawnie. Również (i to jest dla mnie najdziwniejsze), jeśli dodam ten fragment kodu na końcu zapytania, zapytanie działa świetnie:
and t.name like '%'
Doszedłem (być może niepoprawnie) z tych małych eksperymentów, że przyczyną spowolnienia jest sposób, w jaki konfigurowany jest buforowany plan wykonania SQL - gdy zapytanie jest nieco inne, musi utworzyć nowy plan wykonania.
Moje pytanie brzmi: kiedy zapytanie, które kiedyś działało szybko, nagle zaczyna działać powoli w środku nocy i nie ma to wpływu na nic innego oprócz tego jednego zapytania, w jaki sposób go rozwiązać i jak uniknąć tego w przyszłości ? Skąd mam wiedzieć, co SQL robi wewnętrznie, aby spowolnić (jeśli uruchomione zostało niepoprawne zapytanie, mógłbym uzyskać jego plan wykonania, ale nie zadziała - może oczekiwany plan wykonania dałby mi coś?)? Jeśli ten problem dotyczy planu wykonania, jak mogę nie myśleć SQL, że naprawdę kiepskie plany wykonania są dobrym pomysłem?
Nie jest to również problem z wąchaniem parametrów. Widziałem to wcześniej, i to nie wszystko, ponieważ nawet kiedy koduję zmienne w SSMS, wciąż mam niską wydajność.