Запрос SQL Server занимает 100% ЦП и выполняется часами - PullRequest
3 голосов
/ 05 мая 2009

У меня есть запрос, который выполняется каждый день в течение чуть более 2 лет, и на его выполнение обычно уходит менее 30 секунд. Внезапно вчера запрос начал обрабатываться более 3 часов и все время использовал 100% ЦП.

SQL:

SELECT
  @id, 
  alpha.A, alpha.B, alpha.C, 
  beta.X,  beta.Y,  beta.Z, 
  alpha.P, alpha.Q
FROM 
  [DifferentDatabase].dbo.fnGetStuff(@id) beta 
  INNER JOIN vwSomeData alpha ON beta.id = alpha.id

alpha.id - это тип BIGINT, а beta.id - это тип INT. dbo.fnGetStuff() - это простой оператор SELECT с 2 INNER JOIN для таблиц в одной и той же БД, использующий WHERE id = @id. Функция возвращает примерно 11000 результатов.

Представление vwSomeData - это простой оператор SELECT с двумя INNER JOIN, который возвращает около 590000 результатов.

Как просмотр, так и функция завершатся менее чем за 10 секунд, когда они будут выполнены сами по себе. Сначала выберите результаты функции во временной таблице, а затем включите ее, чтобы запрос завершился менее чем через 10 секунд.

Как мне устранить неполадки, что происходит? Я не вижу никаких блокировок в менеджере активности.

Ответы [ 8 ]

4 голосов
/ 05 мая 2009

Посмотрите на план запроса. Я предполагаю, что в плане выполнения есть сканирование таблицы или больше. Это вызовет огромное количество операций ввода-вывода для нескольких записей, которые вы получите в результате.

2 голосов
/ 05 мая 2009

Вы можете использовать инструмент SQL Server Profiler, чтобы отслеживать, какие запросы выполняются на SQL Server. Он не показывает блокировки, но может, например, дать вам советы о том, как улучшить ваш запрос, предложив индексы.

1 голос
/ 06 мая 2009

Вам нужно использовать функцию? Можете ли вы переписать всю вещь в хранимую процедуру, в которой вы передаете @ID в качестве параметра.

Даже если ваша таблица имеет индексы, потому что вы передаете @ID как переменную в предложение WHERE, что потенциально значительно увеличивает время выполнения запроса.

Причина, по которой индексы могут не использоваться, заключается в том, что Query Analyzer не знает значение переменных, когда выбирает метод доступа для выполнения запроса. Поскольку это командный файл, из кода Transact-SQL делается только один проход, что не позволяет Оптимизатору запросов знать, что ему нужно знать для выбора метода доступа, использующего индексы.

Возможно, вы захотите рассмотреть подсказку запроса INDEX, если не можете переписать SQL.

Возможно также, что, поскольку это только начало происходить, ИНДЕКСЫ стали фрагментированными и, возможно, нуждаются в восстановлении.

1 голос
/ 05 мая 2009

Если у вас достаточно свежая версия SQL Server Management Studio, у нее также есть помощник по настройке базы данных в разделе Инструменты. Он берет след от Профилировщика и делает некоторые, иногда очень полезные, предложения. Удостоверится, что запросов не слишком много - для создания рекомендаций требуется много времени.

Я не эксперт в этом, но в прошлом мне повезло.

0 голосов
/ 06 мая 2009

Запустите эту команду:

SET SHOWPLAN_ALL ON

Затем запустите ваш запрос. Он отобразит план выполнения, ищите «СКАНИРОВАНИЕ» в индексе или таблице. Это наиболее вероятно, что происходит с вашим запросом сейчас. Если это так, попробуйте выяснить, почему он не использует индексы (обновить статистику и т. Д.)

0 голосов
/ 05 мая 2009

- не имея представления о типе схемы и просто пытаясь отбросить идеи:

Как и другие говорили ... используйте Profiler и найдите источник боли ... но я думаю, что это функция в другой базе данных. Поскольку эта функция может быть источником боли, вы подумали о небольшой денормализации или о чем-то другом в [DifferentDatabase]. Я думаю, что вы найдете немного более масштабируемым при присоединении к более плоской таблице с индексами, чем дорогостоящая функция.

0 голосов
/ 05 мая 2009

Посмотрите на примерный план, это, вероятно, пролит некоторый свет. Обычно, когда стоимость запроса становится на несколько порядков дороже, это происходит потому, что используется циклическое или слияние слиянием, когда более подходящим является хеш-соединение. Если вы видите цикл или объединение слиянием в предполагаемом плане, посмотрите на число строк, которые он ожидает обработать - намного ли оно меньше, чем число строк, которые, как вы знаете, действительно будут в игре? Вы также можете указать подсказку для использования хеш-соединения и посмотреть, будет ли он работать намного лучше. Если это так, попробуйте обновить статистику и посмотрите, вернется ли она к хеш-соединению без подсказки.

SELECT
  @id, 
  alpha.A, alpha.B, alpha.C, 
  beta.X,  beta.Y,  beta.Z, 
  alpha.P, alpha.Q
FROM 
  [DifferentDatabase].dbo.fnGetStuff(@id) beta 
  INNER HASH JOIN vwSomeData alpha ON beta.id = alpha.id
0 голосов
/ 05 мая 2009

У меня были похожие проблемы с объединением функций, которые возвращают большие наборы данных. Я должен был сделать то, что вы уже предложили. Положите результаты во временную таблицу и присоединитесь к ней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...