Sql-Server

sp_cursoropen 和並行性

  • January 20, 2020

我遇到了一個我似乎無法理解的查詢的性能問題。

我將查詢從游標定義中提取出來。

此查詢需要幾秒鐘才能執行

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)不受支持,但我無法升級此實例,因為我認為合適。我需要將數據庫轉移到另一台伺服器,這意味著通過慢速 WAN 拉取相當大的未壓縮備份。

跟踪標誌 4199 沒有任何區別,OPTION (RECOMPILE) 也沒有。

游標屬性為:

API | Fast_Forward | Read Only | Global (0)

FAST_FORWARD游標不支持並行性(儘管生成計劃的伺服器需要 2012 或更高版本才能NonParallelPlanReason作為 showplan XML 的一部分獲得)。

當您指定FAST_FORWARD時,優化器會為您選擇STATICDYNAMIC

提供的執行計劃顯示優化器選擇了一個類似靜態的計劃。因為查詢包含聚合,我懷疑動態游標計劃在這裡甚至是可能的。然而,請求FAST_FORWARD游標類型會阻止並行計劃。

例如,您應該將游標類型顯式更改為STATICKEYSET。這兩種游標類型都可以使用並行性。

也就是說,因為這是一個 API 游標,所以更改游標類型可能需要更改應用程序。自然,您需要對性能進行基準測試,以檢查更改游標類型是否真的是您的最佳選擇。

引用自:https://dba.stackexchange.com/questions/106454