Задний план
У меня есть запрос к 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, я все равно получаю низкую производительность.
Ответы:
Вы можете начать с проверки, находится ли план выполнения в кэше. Проверьте
sys.dm_exec_query_stats
,sys.dm_exec_procedure_stats
иsys.dm_exec_cached_plans
. Если неверный план выполнения все еще кэшируется, вы можете проанализировать его и проверить статистику выполнения. Статистика выполнения будет содержать информацию в виде логических чтений, времени процессора и времени выполнения. Это может дать четкие указания о том, в чем заключается проблема (например, большое сканирование или блокировка). См. Идентификация проблемных запросов для объяснения, как интерпретировать данные.Я не убежден. Жесткое кодирование переменных в SSMS не доказывает, что прошлый неверный план выполнения не был скомпилирован с искаженным вводом. Пожалуйста, прочитайте Параметры Sniffing, Embedding и RECOMPILE Options для очень хорошей статьи на эту тему. Медленно в приложении, быстро в SSMS? Понимание загадок производительности - еще одна отличная ссылка.
Это можно легко проверить.
SET STATISTICS TIME ON
покажет вам время компиляции и выполнения. SQL Server: статистические счетчики производительности также покажут, является ли проблема компиляции (честно говоря, я нахожу это маловероятным).Однако есть нечто похожее, что вы можете поразить: ворота предоставления запроса. Прочитайте раздел Понимание предоставления памяти SQL-серверу для получения подробной информации Если ваш запрос запрашивает большой грант в тот момент, когда нет доступной памяти, ему придется подождать, и все это будет выглядеть как «медленное выполнение» для приложения. Анализ статистики ожидания покажет, если это так.
Для более общего обсуждения того, что измерять и что искать, см. Как анализировать производительность SQL Server.
источник
Это проблема выполнения сложных запросов в SQL Server. К счастью, это случается не так часто.
Посмотрите на план запроса для запроса (когда он работает медленно). Я предполагаю, что вы найдете объединение с вложенным циклом, встречающееся один или несколько раз в таблицах без индексов для объединения. Это действительно замедляет ход событий. Чтобы перемотать вперед, способ исправить это с подсказкой. Добавьте следующее в конце запроса:
Это обычно исправляло эту проблему для меня в прошлом.
Может случиться так, что незначительные изменения в таблице (или доступности временного пространства) заставляют оптимизатор SQL предпочитать более медленный алгоритм объединения. Это может быть довольно тонким и довольно внезапным. Когда вы создаете временную таблицу, оптимизатор имеет больше информации о таблице (например, ее размер), поэтому он может сгенерировать лучший план.
источник
Обычно это отсутствующий индекс, вызывающий подобные проблемы.
Обычно я выполняю запрос с использованием SQL Management Studio и включаю «Включить фактический план выполнения (CTRL + M)» и выясняю, какое объединение имеет наибольший процент.
Приложение не фокусируется на узких местах, но вы можете найти его «быстро», просто взглянув на результат.
пример здесь:
источник
Недавно я столкнулся с той же проблемой, которая привела меня на эту страницу.
@MartinSmith был о чем-то, когда он рекомендовал обновить вашу статистику и объяснить план. Я хотел бы добавить, что вы должны также постараться убедиться, что вы смотрите на запущенные задания / запросы, которые могут создавать блокировки и тем самым замедлять время отклика.
В моем случае виновником была сбор статистики по работе. По какой-то причине он не завершился в окне, которое должно было появиться, и продолжал работать, когда пользователи возобновили работу. Я нашел процесс, убил его, и запросы снова начали отвечать.
Я надеюсь, что это помогает кому-то еще
источник
Вам также необходимо проверить, выполняются ли какие-либо резервные копии сервера или задания архивирования \ индексирования, когда вы видите проблему с производительностью в T-SQL \ Процедура.
источник