sp_cursoropen y paralelismo


15

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í.

ingrese la descripción de la imagen aquí

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.

ingrese la descripción de la imagen aquí

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).

ingrese la descripción de la imagen aquí

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)

Respuestas:


20

FAST_FORWARDlos cursores no admiten paralelismo (aunque el servidor que genera el plan debería ser 2012 o superior para obtenerlo NonParallelPlanReasoncomo parte del XML del plan de presentación).

Cuando especificas FAST_FORWARD, el optimizador elige entre STATICy DYNAMICpara ti.

El plan de ejecución proporcionado muestra al optimizador eligiendo un plan de tipo estático. Debido a que la consulta contiene agregación, dudo que sea posible un plan de cursor dinámico aquí. Sin embargo, solicitar un FAST_FORWARDtipo de cursor impide un plan paralelo.

Debe cambiar el tipo de cursor explícitamente a cualquiera STATICo KEYSET, por ejemplo. Ambos tipos de cursor pueden usar paralelismo.

Dicho esto, debido a que este es un cursor de API, cambiar el tipo de cursor probablemente requerirá un cambio de aplicación. Naturalmente, necesitaría comparar el rendimiento para verificar que cambiar el tipo de cursor realmente sea la mejor opción para usted.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.