Одинаковые (?) Машины SQL Server 2005; запрос занимает 2 секунды на одном, 15 минут на другом

12

Окружение:

У нас есть два 32-разрядных компьютера с Windows Server 2003 R2 под управлением SQL Server 2005. Аппаратные конфигурации - это идентичные серверы с процессором Xeon 5160, 4 ГБ ОЗУ и 13 ГБ RAID0. Флаги AWE и / 3GB не включены.

Серверы были установлены параллельно с использованием предварительно определенного контрольного списка установки, и ВСЕ установленное программное обеспечение одинаково на обеих машинах.

Все установки SQL-сервера и уровень исправлений, которые мы проверяем, идентичны. Одно из отличий состоит в том, что TEMPDB составляет 400 МБ на быстрой машине и 1,2 ГБ на медленной. Однако в обоих случаях мы не видим распределения TEMPDB.

Проблема:

Существует хранимая процедура, которая выполняется за 2 секунды на одной, но 15 минут на другой. В течение дополнительных 15 минут активность диска практически отсутствует, использование памяти не изменяется, но одно ядро ​​ЦП закреплено на все 100%.

Такое поведение сохраняется даже при резервном копировании баз данных из одной и восстановлении в другой.

Поскольку это хранимая процедура, монитор активности и профилировщик не показывают нам каких-либо подробностей о том, где в хранимой процедуре происходит такая высокая загрузка ЦП.

Вопрос:

На что еще мы должны смотреть?

Следовать за:

Замедление происходит в операторах FETCH NEXT для следующего определения курсора:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE X NOT IN (SELECT X FROM dbo.B)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
...

Каждый из операторов FETCH - в таблице, содержащей только около 1000 строк - требует около 7,25 минут. (Нет, я не знаю, почему он делает два подряд, нужно спросить разработчиков, но он работает правильно на обоих серверах).

Я немного подозрительно отношусь к этому «NOT IN (SELECT ...)», поскольку похоже, что Virtual Reads действительно высоко.

ryandenki
источник
Как записи в dbo.B и dbo.BX индексируются?
Марк Стори-Смит
1
Мне любопытно, будет ли разница в производительности, если вы пойдете с этим: выберите dbo.ax, dbo.ay из dbo.a, оставив внешнее соединение dbo.b на dbo.ax = dbo.bx, где dbo.bx равно нулю и z <= 0
DForck42
Еще одна мысль, чтобы добавить в смесь. Вы уверены, что замедление происходит из-за извлечения курсора? Вы определяете это из плана выполнения (который все об оценках) или из трассы профиля?
Марк Стори-Смит
Это от следа профиля.
рянденки
Планы выполнения одинаковы? Возможно, один из них использует неверный план выполнения.
Зейн

Ответы:

7

Используя методологию устранения неполадок с производительностью, такую ​​как « Ожидания» и «Очереди», выявляют причину высокой загрузки ЦП, затем можно рекомендовать соответствующие действия после выявления узкого места.

Ремус Русану
источник
6

SQL Server выбирает другой план в другом окне.

Восстановление обычно удаляет проблемы, основанные на статистике, поэтому я бы посмотрел на различия сервера.

Сначала несколько грубых проверок. Не предполагайте: проверьте

  • Убедитесь, что параметры SQL Server одинаковы в sys.configuration, например, максимальная степень или параллелизм
  • Запустите DBCC USEROPTIONS, чтобы увидеть, отличаются ли какие-либо настройки ANSI во время выполнения (настройки ANS могут повлиять на выбранный план)
  • Проверьте журналы Windows и SQL Server, чтобы увидеть, есть ли какие-либо проблемы

Затем прыгайте в глубокий конец, как и в ответе Ремуса.

ГБН
источник
Спасибо за подсказки. И sys.configurations, и DBCC USEROPTIONS идентичны между двумя компьютерами. Нет ошибок или предупреждений в журналах Windows или SQL-сервера.
1
И они также управляют идентичной структурой базы данных? Не планируете ли администратор проводить оптимизации (перестроение индекса и т. Д.), Базы данных имеют одинаковую статистику для соответствующих объектов и одинаковую разметку диска? Тот же уровень патча?
TomTom
Да, тот же диск, структура БД и уровень исправлений. Фактически, база данных на быстрой машине - это восстановленная резервная копия с медленной машины. И нет никаких планов администратора, которые меняются, насколько я вижу.
ryandenki
6

Если все остальные вещи равны, вероятно (согласно ответу @ gbn), что на каждом сервере генерируется другой план выполнения. В качестве академического упражнения было бы интересно увидеть оба плана, поэтому возьмите их из кэша планов на каждом сервере и добавьте их в свой вопрос, если это возможно. Затем мы можем определить различия в планах, которые вызывают такие большие различия в производительности.

Для быстрого исправления взгляните на подсказку USE PLAN . Это позволяет прикрепить хороший план с быстрого сервера к хранимой процедуре на медленном сервере.

Редактировать: следующее обновление: курсор

Еще один вариант вашего запроса, который я не вижу в других ответах:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE NOT EXISTS (SELECT 1 FROM dbo.B WHERE dbo.B.X = dbo.A.X)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
Марк Стори-Смит
источник
Это хороший совет, мы проверяем планы запросов. На самом деле замедление хранимой процедуры, похоже, связано с курсором. Смотрите редактировать.
ryandenki
4

Приколите меня и попробуйте заменить:

DECLARE C CURSOR FOR
SELECT X, Y
FROM dbo.A
WHERE X NOT IN (SELECT X FROM dbo.B)
AND Z <=0

с этим:

DECLARE C CURSOR FOR
SELECT 
    X, 
    Y
FROM dbo.A

    LEFT OUTER JOIN dbo.B
        ON dbo.A.X = dbo.b.X

WHERE dbo.B.X IS NULL
AND Z <=0

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

Надеюсь это поможет,

Matt

Мэтт М
источник
4

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

DForck42
источник
1

Я испытывал такое же поведение дважды, и я скажу вам, что исправило это каждый раз:

1.) Я добавил подсказку WITH RECOMPILE к хранимой процедуре, потому что кэшированный план был ужасен.

2.) Я изменил хранимую процедуру, чтобы использовать временные таблицы вместо табличных переменных.

Я надеюсь, что любой из этих поможет. Удачи.

Джон
источник