sp_cursoropen und Parallelität

15

Ich habe ein Leistungsproblem mit einer Abfrage, die mir nicht klar ist.

Ich habe die Abfrage aus einer Cursordefinition gezogen.

Die Ausführung dieser Abfrage dauert Sekunden

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

Der tatsächliche Ausführungsplan sieht so aus.

Bildbeschreibung hier eingeben

Beachten Sie, dass die serverweite Einstellung auf MaxDOP 1 festgelegt wurde. Ich habe versucht, mit den maxdop-Einstellungen herumzuspielen.

Durch Hinzufügen OPTION (MAXDOP 0)zur Abfrage oder Ändern der Servereinstellungen werden die Leistung und der Abfrageplan erheblich verbessert.

Bildbeschreibung hier eingeben

Die betreffende Anwendung (Dynamics AX) führt jedoch keine derartigen Abfragen aus, sondern verwendet Cursor.

Der tatsächlich erfasste Code ist dieser.

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

Daraus resultiert dieser Ausführungsplan (und leider die gleichen Ausführungszeiten von mehreren Sekunden).

Bildbeschreibung hier eingeben

Ich habe verschiedene Dinge ausprobiert, wie das Löschen von zwischengespeicherten Plänen, das Hinzufügen von Optionen in der Abfrage innerhalb der Cursordefinition, ... Aber keiner von ihnen scheint mir einen parallelen Plan zu liefern.

Ich habe auch in Google nach Parallelitätsbeschränkungen von Cursorn gesucht, kann aber anscheinend keine Einschränkungen feststellen.

Vermisse ich hier etwas Offensichtliches?

Der eigentliche SQL-Build wird SQL Server 2008 (SP1) - 10.0.2573.0 (X64)meines Erachtens nicht unterstützt, aber ich kann diese Instanz nicht aktualisieren, wie ich es für richtig halte. Ich müsste die Datenbank auf einen anderen Server übertragen, und das würde bedeuten, eine ziemlich große unkomprimierte Sicherung über ein langsames WAN zu ziehen.

Das Trace-Flag 4199 macht keinen Unterschied und OPTION (RECOMPILE) auch nicht.

Die Cursoreigenschaften sind:

API | Fast_Forward | Read Only | Global (0)
Tom V - Team Monica
quelle

Antworten:

20

FAST_FORWARDCursor unterstützen keine Parallelität (obwohl der Server, der den Plan erstellt, NonParallelPlanReasonmindestens 2012 sein muss, um als Teil des Showplan-XML zu erhalten).

Wenn Sie angeben FAST_FORWARD, wählt der Optimierer zwischen STATICund DYNAMICfür Sie aus.

Der bereitgestellte Ausführungsplan zeigt, wie der Optimierer einen statischen Plan auswählt. Da die Abfrage eine Aggregation enthält, bezweifle ich, dass hier sogar ein dynamischer Cursorplan möglich ist. Das Anfordern eines FAST_FORWARDCursortyps verhindert jedoch einen parallelen Plan.

Sie sollten den Cursortyp beispielsweise explizit in entweder STATICoder ändern KEYSET. Beide Cursortypen können Parallelität verwenden.

Da es sich jedoch um einen API-Cursor handelt, ist für das Ändern des Cursortyps wahrscheinlich eine Anwendungsänderung erforderlich. Natürlich müssten Sie die Leistung bewerten, um zu überprüfen, ob das Ändern des Cursortyps die beste Option für Sie ist.

Paul White Monica wieder einsetzen
quelle