Задний план
У меня есть запрос к SQL Server 2008 R2, который объединяет и / или объединяет влево около 12 различных «таблиц». База данных довольно большая, со многими таблицами более 50 миллионов строк и около 300 различных таблиц. Это для крупной компании, которая имеет 10 складов по всей стране. Все склады читают и пишут в базу данных. Так что он довольно большой и довольно занятый.
Запрос, с которым у меня возникли проблемы, выглядит примерно так:
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
Обратите внимание, что одно из объединений находится на некоррелированном подзапросе.
Проблема в том, что начиная с этого утра, без каких-либо изменений (о которых я или кто-либо из моей команды знаю) в системе, запрос, который обычно занимает около 2 минут, начинает работать полтора часа - когда он побежал на всех. Остальная часть базы данных гудит просто отлично. Я взял этот запрос из sproc, в котором он обычно выполняется, и запустил его в SSMS с жестко запрограммированными переменными параметров с той же медлительностью.
Странность заключается в том, что когда я беру некоррелированный подзапрос и бросаю его во временную таблицу, а затем использую его вместо подзапроса, запрос выполняется нормально. Также (и это самое странное для меня), если я добавлю этот фрагмент кода в конец запроса, запрос будет работать отлично:
and t.name like '%'
Из этих небольших экспериментов я сделал вывод (возможно, неверно), что причина замедления заключается в том, как настроен кэшированный план выполнения SQL - когда запрос немного отличается, он должен создать новый план выполнения.
Мой вопрос заключается в следующем: когда запрос, который раньше выполнялся быстро, внезапно начинает выполняться медленно среди ночи, и ничто другое не затрагивается, за исключением этого одного запроса, как мне устранить его и как предотвратить его в будущем ? Как мне узнать, что SQL делает внутренне, чтобы сделать его таким медленным (если бы некорректный запрос выполнялся, я мог бы получить план его выполнения, но он не запустится - может быть, ожидаемый план выполнения мне что-нибудь даст?)? Если эта проблема связана с планом выполнения, как мне не допустить, чтобы SQL думал, что действительно дурацкие планы выполнения - это хорошая идея?
Кроме того, это не проблема с анализом параметров. Я видел это раньше, и это не так, потому что даже когда я жестко программирую переменные в SSMS, я все равно получаю низкую производительность.