sp_cursoropen 和并行性

Tom*_*m V 15 performance sql-server parallelism cursors microsoft-dynamics query-performance

我遇到了一个查询的性能问题,我似乎无法理解。

我从游标定义中提取了查询。

此查询需要几秒钟才能执行

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
Run Code Online (Sandbox Code Playgroud)

实际的执行计划是这样的。

在此处输入图片说明

注意到服务器范围的设置被设置为 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
Run Code Online (Sandbox Code Playgroud)

导致这个执行计划(不幸的是相同的多秒执行时间)。

在此处输入图片说明

我已经尝试了几种方法,例如删除缓存计划,在游标定义内的查询中添加选项,......但它们似乎都没有给我一个并行计划。

我也在谷歌上搜索了很多,寻找游标的并行性限制,但似乎找不到任何限制。

我在这里遗漏了一些明显的东西吗?

实际的 SQL 构建是SQL Server 2008 (SP1) - 10.0.2573.0 (X64)我意识到不受支持的,但我无法按照我认为合适的方式升级此实例。我需要将数据库传输到另一台服务器,这意味着通过慢速 WAN 提取相当大的未压缩备份。

跟踪标志 4199 没有区别,OPTION (RECOMPILE) 也没有区别。

游标属性是:

API | Fast_Forward | Read Only | Global (0)
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 20

FAST_FORWARD游标不支持并行性(尽管生成计划的服务器需要是 2012 年或更高版本才能NonParallelPlanReason作为 showplan XML 的一部分)。

当您指定 时FAST_FORWARD优化器会STATIC和之间进行选择DYNAMIC

提供的执行计划显示优化器选择静态计划。因为查询包含聚合,我怀疑动态游标计划在这里是否可行。然而,请求FAST_FORWARD游标类型会阻止并行计划。

例如,您应该将游标类型显式更改为STATICKEYSET。这两种游标类型都可以使用并行性。

也就是说,因为这是一个 API 游标,更改游标的类型可能需要更改应用程序。自然,您需要对性能进行基准测试,以检查更改游标类型是否确实是您的最佳选择。