Sto riscontrando un problema di prestazioni con una query che non riesco a capire.
Ho estratto la query da una definizione del cursore.
Questa query richiede pochi secondi per essere eseguita
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
Il piano di esecuzione effettivo è simile al seguente.
Notando che l'impostazione a livello di server è stata impostata su MaxDOP 1, ho provato a giocare con le impostazioni di maxdop.
Aggiungendo OPTION (MAXDOP 0)
alla query o modificando le impostazioni del server si ottengono prestazioni molto migliori e questo piano di query.
Tuttavia, l'applicazione in questione (Dynamics AX) non esegue query come questa, utilizza i cursori.
Il vero codice acquisito è questo.
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
risultante in questo piano di esecuzione (e purtroppo gli stessi tempi di esecuzione di più secondi).
Ho provato diverse cose come eliminare i piani memorizzati nella cache, aggiungere opzioni nella query all'interno della definizione del cursore, ... Ma nessuno di loro sembra farmi un piano parallelo.
Ho anche cercato su Google un po 'alla ricerca di limiti di parallelismo dei cursori, ma non riesco a trovare alcun limite.
Mi sto perdendo qualcosa di ovvio qui?
L'effettivo build SQL è SQL Server 2008 (SP1) - 10.0.2573.0 (X64)
che mi rendo conto che non è supportato, ma non posso aggiornare questa istanza a mio avviso. Avrei bisogno di trasferire il database su un altro server e ciò significherebbe eseguire il pull di un backup non compresso abbastanza grande su una WAN lenta.
Il flag di traccia 4199 non fa differenza, e nemmeno OPTION (RECOMPILE).
Le proprietà del cursore sono:
API | Fast_Forward | Read Only | Global (0)