Me encuentro con un problema de rendimiento con una consulta que parece que no puedo entender.
Saqué la consulta de una definición de cursor.
Esta consulta tarda unos segundos en ejecutarse
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
El plan de ejecución real se ve así.
Al notar que la configuración de todo el servidor estaba configurada en MaxDOP 1, intenté jugar con la configuración de maxdop.
Agregar OPTION (MAXDOP 0)
a la consulta o cambiar la configuración del servidor da como resultado un rendimiento mucho mejor y este plan de consulta.
Sin embargo, la aplicación en cuestión (Dynamics AX) no ejecuta consultas como esta, usa cursores.
El código real capturado es este.
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
resultando en este plan de ejecución (y desafortunadamente los mismos tiempos de ejecución de varios segundos).
He intentado varias cosas, como soltar planes en caché, agregar opciones en la consulta dentro de la definición del cursor, ... Pero ninguno de ellos parece obtener un plan paralelo.
También busqué en Google bastante buscando las limitaciones de paralelismo de los cursores, pero parece que no puedo encontrar ninguna limitación.
¿Me estoy perdiendo algo obvio aquí?
La construcción de SQL real es la SQL Server 2008 (SP1) - 10.0.2573.0 (X64)
que me doy cuenta de que no es compatible, pero no puedo actualizar esta instancia como lo considero apropiado. Necesitaría transferir la base de datos a otro servidor y eso significaría extraer una copia de seguridad sin comprimir bastante grande sobre una WAN lenta.
La marca de seguimiento 4199 no hace la diferencia, y tampoco lo hace la OPCIÓN (RECOMPILAR).
Las propiedades del cursor son:
API | Fast_Forward | Read Only | Global (0)
fuente