sp_cursoropen и параллелизм


15

Я столкнулся с проблемой производительности с запросом, который, кажется, не может заставить меня задуматься.

Я вытащил запрос из определения курсора.

Этот запрос занимает несколько секунд, чтобы выполнить

SELECT A.JOBTYPE
FROM PRODROUTEJOB A
WHERE ((A.DATAAREAID=N'IW')
AND ((A.CALCTIMEHOURS<>0)
AND (A.JOBTYPE<>3)))
AND EXISTS (SELECT 'X'
FROM PRODROUTE B
WHERE ((B.DATAAREAID=N'IW')
AND (((((B.PRODID=A.PRODID)
AND ((B.PROPERTYID=N'PR1526157') OR (B.PRODID=N'PR1526157')))
AND (B.OPRNUM=A.OPRNUM))
AND (B.OPRPRIORITY=A.OPRPRIORITY))
AND (B.OPRID=N'GRIJZEN')))
AND NOT EXISTS (SELECT 'X'
FROM ADUSHOPFLOORROUTE C
WHERE ((C.DATAAREAID=N'IW')
AND ((((((C.WRKCTRID=A.WRKCTRID)
AND (C.PRODID=B.PRODID))
AND (C.OPRID=B.OPRID))
AND (C.JOBTYPE=A.JOBTYPE))
AND (C.FROMDATE>{TS '1900-01-01 00:00:00.000'}))
AND ((C.TODATE={TS '1900-01-01 00:00:00.000'}))))))
GROUP BY A.JOBTYPE
ORDER BY A.JOBTYPE

Фактический план выполнения выглядит следующим образом.

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

Заметив, что для параметра сервера установлено значение MaxDOP 1 Я попытался поиграться с настройками maxdop.

Добавление OPTION (MAXDOP 0)к запросу или изменение настроек сервера приводит к гораздо большей производительности и этому плану запроса.

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

Однако рассматриваемое приложение (Dynamics AX) не выполняет подобные запросы, оно использует курсоры.

Фактический код захвачен это.

declare @p1 int
set @p1=189527589
declare @p3 int
set @p3=16
declare @p4 int
set @p4=1
declare @p5 int
set @p5=2
exec sp_cursoropen @p1 output,N'SELECT A.JOBTYPE FROM PRODROUTEJOB A WHERE ((A.DATAAREAID=N''IW'') AND ((A.CALCTIMEHOURS<>0) AND (A.JOBTYPE<>3))) AND EXISTS (SELECT ''X'' FROM PRODROUTE B WHERE ((B.DATAAREAID=N''IW'') AND (((((B.PRODID=A.PRODID) AND ((B.PROPERTYID=N''PR1526157'') OR (B.PRODID=N''PR1526157''))) AND (B.OPRNUM=A.OPRNUM)) AND (B.OPRPRIORITY=A.OPRPRIORITY)) AND (B.OPRID=N''GRIJZEN''))) AND NOT EXISTS (SELECT ''X'' FROM ADUSHOPFLOORROUTE C WHERE ((C.DATAAREAID=N''IW'') AND ((((((C.WRKCTRID=A.WRKCTRID) AND (C.PRODID=B.PRODID)) AND (C.OPRID=B.OPRID)) AND (C.JOBTYPE=A.JOBTYPE)) AND (C.FROMDATE>{TS ''1900-01-01 00:00:00.000''})) AND ((C.TODATE={TS ''1900-01-01 00:00:00.000''})))))) GROUP BY A.JOBTYPE ORDER BY A.JOBTYPE ',@p3 output,@p4 output,@p5 output
select @p1, @p3, @p4, @p5

в результате этого плана выполнения (и, к сожалению, то же время выполнения несколько секунд).

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

Я пробовал несколько вещей, таких как удаление кэшированных планов, добавление опций в запросе внутри определения курсора ... Но, похоже, ни одна из них не дает мне параллельный план.

Я также искал в Google довольно много в поисках ограничений параллельности курсоров, но не могу найти никаких ограничений.

Я что-то упускаю здесь очевидное?

Реальная сборка SQL, как SQL Server 2008 (SP1) - 10.0.2573.0 (X64)я понимаю, не поддерживается, но я не могу обновить этот экземпляр так, как считаю нужным. Мне нужно было перенести базу данных на другой сервер, и это означало бы перетаскивание довольно большой несжатой резервной копии по медленной глобальной сети.

Флаг трассировки 4199 не имеет значения, равно как и OPTION (RECOMPILE).

Свойства курсора:

API | Fast_Forward | Read Only | Global (0)

Ответы:


20

FAST_FORWARDкурсоры не поддерживают параллелизм (хотя сервер, генерирующий план, должен быть 2012 или выше, чтобы получить его NonParallelPlanReasonкак часть XML showplan).

Когда вы указываете FAST_FORWARD, оптимизатор выбирает между вами STATICи DYNAMICдля вас.

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

Вы должны явно изменить тип курсора либо на, STATICлибо KEYSET, например. Оба эти типа курсора могут использовать параллелизм.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.