разница в планах выполнения на сервере UAT и PROD

39

Я хочу понять, почему была бы такая огромная разница в выполнении одного и того же запроса в UAT (выполняется за 3 секунды) по сравнению с PROD (выполняется за 23 секунды).

И UAT, и PROD имеют именно данные и индексы.

QUERY:

set statistics io on;
set statistics time on;

SELECT CONF_NO,
       'DE',
       'Duplicate Email Address ''' + RTRIM(EMAIL_ADDRESS) + ''' in Maintenance',
       CONF_TARGET_NO
FROM   CONF_TARGET ct
WHERE  CONF_NO = 161
       AND LEFT(INTERNET_USER_ID, 6) != 'ICONF-'
       AND ( ( REGISTRATION_TYPE = 'I'
               AND (SELECT COUNT(1)
                    FROM   PORTFOLIO
                    WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                           AND DEACTIVATED_YN = 'N') > 1 )
              OR ( REGISTRATION_TYPE = 'K'
                   AND (SELECT COUNT(1)
                        FROM   CAPITAL_MARKET
                        WHERE  EMAIL_ADDRESS = ct.EMAIL_ADDRESS
                               AND DEACTIVATED_YN = 'N') > 1 ) ) 

В УАТ:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 11 ms, elapsed time = 11 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'Worktable'. Scan count 256, logical reads 1304616, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PORTFOLIO'. Scan count 1, logical reads 84761, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 2418 ms,  elapsed time = 2442 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

введите описание изображения здесь

На ПРОД:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(3 row(s) affected)
Table 'PORTFOLIO'. Scan count 256, logical reads 21698816, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CAPITAL_MARKET'. Scan count 256, logical reads 9472, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CONF_TARGET'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 23937 ms,  elapsed time = 23935 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

введите описание изображения здесь

Обратите внимание, что в PROD запрос предлагает отсутствующий индекс, и это полезно, как я уже тестировал, но это не предмет обсуждения.

Я просто хочу понять, что: ON UAT - почему сервер sql создает рабочую таблицу, а на PROD - нет? Он создает таблицу на UAT, а не на PROD. Кроме того, почему время выполнения так отличается в UAT от PROD?

Заметка :

Я запускаю sql server 2008 R2 RTM на обоих серверах (довольно скоро собираюсь установить патч с последним SP).

UAT: максимальная память 8 ГБ. MaxDop, сродство процессора и максимальное количество рабочих потоков равно 0.

Logical to Physical Processor Map:
*-------  Physical Processor 0
-*------  Physical Processor 1
--*-----  Physical Processor 2
---*----  Physical Processor 3
----*---  Physical Processor 4
-----*--  Physical Processor 5
------*-  Physical Processor 6
-------*  Physical Processor 7

Logical Processor to Socket Map:
****----  Socket 0
----****  Socket 1

Logical Processor to NUMA Node Map:
********  NUMA Node 0

PROD: максимальная память 60 ГБ. MaxDop, сродство процессора и максимальное количество рабочих потоков равно 0.

Logical to Physical Processor Map:
**--------------  Physical Processor 0 (Hyperthreaded)
--**------------  Physical Processor 1 (Hyperthreaded)
----**----------  Physical Processor 2 (Hyperthreaded)
------**--------  Physical Processor 3 (Hyperthreaded)
--------**------  Physical Processor 4 (Hyperthreaded)
----------**----  Physical Processor 5 (Hyperthreaded)
------------**--  Physical Processor 6 (Hyperthreaded)
--------------**  Physical Processor 7 (Hyperthreaded)

Logical Processor to Socket Map:
********--------  Socket 0
--------********  Socket 1

Logical Processor to NUMA Node Map:
********--------  NUMA Node 0
--------********  NUMA Node 1

ОБНОВИТЬ :

План выполнения UAT XML:

http://pastebin.com/z0PWvw8m

План выполнения PROD XML:

http://pastebin.com/GWTY16YY

XML плана выполнения UAT - с планом, сгенерированным для PROD:

http://pastebin.com/74u3Ntr0

Конфигурация сервера:

PROD: PowerEdge R720xd - процессор Intel® Xeon®® E5-2637 v2 @ 3,50 ГГц.

UAT: PowerEdge 2950 - процессор Intel® Xeon®® X5460 с частотой 3,16 ГГц

Я разместил на answers.sqlperformance.com


ОБНОВИТЬ :

Спасибо @swasheck за предложение

Изменяя максимальный объем памяти в PROD с 60 ГБ до 7680 МБ, я могу создать тот же план в PROD. Запрос завершается в то же время, что и UAT.

Теперь мне нужно понять - ПОЧЕМУ? Кроме того, этим я не смогу оправдать замену старого сервера этим чудовищным сервером!

Кин Шах
источник

Ответы:

43

Потенциальный размер пула буферов влияет на выбор плана оптимизатором запросов несколькими способами. Насколько я знаю, гиперпоточность не влияет на выбор плана (хотя количество потенциально доступных планировщиков, безусловно, может).

Память рабочего пространства

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

В SQL Server 2012 (все версии) это число указывается в корневом узле плана запроса в Optimizer Hardware Dependenciesразделе, обозначенном как Estimated Available Memory Grant. Версии до 2012 не сообщают этот номер в плане показа.

Предполагаемое предоставление доступной памяти является входом в модель затрат, используемую оптимизатором запросов. В результате альтернатива плана, которая требует большой операции сортировки или хеширования, с большей вероятностью будет выбрана на машине с настройкой большого буферного пула, чем на машине с более низкой настройкой. Для установок с очень большим объемом памяти модель затрат может зайти слишком далеко с таким типом мышления - выбор планов с очень большими сортировками или хэшами, где предпочтительна альтернативная стратегия ( KB2413549 - Использование больших объемов памяти может привести к неэффективный план в SQL Server - TF2335 ).

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

Доступ к данным

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

Сканирование кластерного индекса в планах запросов, показанных в вопросе, является одним из примеров повторного доступа; сканы перематываются (повторяются, без изменения коррелированного параметра) для каждой итерации полусоединения вложенных циклов. Внешний вход в полусоединение оценивает 28,7874 строки, и в результате свойства плана запроса для этих сканирований показывают предполагаемые перемотки в 27,7874.

Опять же, только в SQL Server 2012, корневой итератор плана показывает число Estimated Pages Cachedв Optimizer Hardware Dependenciesразделе. Это число сообщает об одном из входных данных алгоритму калькуляции, который учитывает вероятность повторного доступа к странице из кэша.

Эффект состоит в том, что установка с более высоким настроенным максимальным размером пула буферов будет иметь тенденцию к снижению затрат на сканирование (или поиск), которые читают одни и те же страницы более одного раза, чем установка с меньшим максимальным размером пула буферов.

В простых планах снижение затрат на сканирование с перемоткой можно увидеть, сравнив (estimated number of executions) * (estimated CPU + estimated I/O)с оценочной стоимостью оператора, которая будет ниже. Расчет в планах примера более сложен из-за эффекта полусоединения и объединения.

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

Выбор плана

Модель затрат оптимизатора делает ряд допущений и содержит большое количество подробных расчетов. Не всегда (или даже обычно) невозможно проследить все детали, потому что раскрыты не все числа, которые нам нужны, и алгоритмы могут меняться между выпусками. В частности, формула масштабирования, применяемая для учета вероятности обнаружения кэшированной страницы, недостаточно известна.

Более того, в данном конкретном случае выбор плана оптимизатора в любом случае основан на неправильных числах. Предполагаемое количество строк из поиска кластерного индекса составляет 28,7874, тогда как 256 строк встречаются во время выполнения - почти на порядок меньше. Мы не можем напрямую увидеть информацию, которую оптимизатор имеет об ожидаемом распределении значений в этих 28,7874 строках, но, скорее всего, это будет ужасно неправильно.

Если оценки неверны, выбор плана и производительность во время выполнения не лучше, чем случайность. План с индексом золотника происходит работать лучше , чем повторять сканирование, но это совершенно неправильно думать , что увеличение размера пула буферов был причиной аномалии.

Там, где у оптимизатора есть правильная информация, гораздо больше шансов, что он даст достойный план выполнения. Экземпляр с большим объемом памяти обычно работает лучше при рабочей нагрузке, чем другой экземпляр с меньшим объемом памяти, но нет никаких гарантий, особенно когда выбор плана основан на неверных данных.

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

Пол Уайт говорит, что GoFundMonica
источник
18

Пол Уайт прекрасно объяснил причину - поведение сервера sql при работе на серверах с большим объемом памяти.

Также огромное спасибо @swasheck за первое обнаружение проблемы.

Открыл дело с майкрософт и ниже то что было предложено.

Проблема решена путем использования флага трассировки T2335 в качестве параметра запуска.

KB2413549 - Использование больших объемов памяти может привести к неэффективному плана в SQL Server описывает это более подробно.

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

Кин Шах
источник
13

Максимальные настройки памяти и гиперпоточность могут повлиять на выбор плана.

Кроме того, я замечаю, что ваши «установленные» параметры отличаются в каждой среде:

StatementSetOptions на UAT:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="true" 
CONCAT_NULL_YIELDS_NULL="true" 
NUMERIC_ROUNDABORT="false" 
QUOTED_IDENTIFIER="true" 

StatementSetOptions на Prod:

ANSI_NULLS="true" 
ANSI_PADDING="true" 
ANSI_WARNINGS="true" 
ARITHABORT="false" 
CONCAT_NULL_YIELDS_NULL="true"
NUMERIC_ROUNDABORT="false"
QUOTED_IDENTIFIER="true" 

SQL может генерировать разные планы на основе параметров SET. Это часто происходит, если вы захватываете план из разных сеансов SSMS или из разных исполнений из приложения.

Убедитесь, что разработчики используют согласованные строки подключения.

rottengeek
источник
2
Вы правы, утверждая, что Max Memory и Hyperthreading могут влиять на кэш плана, но я хочу подробно узнать, что и почему это произошло. Ценю ваш ответ.
Кин Шах
2
Как сказала Аманда, если параметры SET отличаются в ARITHABORT, возможно, вам следует обратиться к dba.stackexchange.com/questions/9840/…
ARA