Plan de consulta estimado versus real con llamadas a funciones


11

Tengo esta consulta en el servidor SQL, una consulta de replicación de fusión:

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

El plan de consulta estimado incluye información sobre 3 consultas:

  1. La consulta anterior
  2. La llamada de función a fn_MSgeneration_downloadonly
  3. La llamada de función a fn_MSArticle_has_downloadonly_property

El plan de consulta real incluye solo esta información:

  1. La consulta anterior

Nada sobre las funciones. ¿Por qué falta la información de la función en el plan real?

Probé estas opciones:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

Lo que creó un plan real, pero le faltaban las partes 2 y 3 igual que cuando usé la opción de plan de consulta real en Management Studio.

Si, por ejemplo, tuviera que usar Profiler para capturar la información sobre las llamadas a funciones, ¿qué eventos seleccionaría?


No encontré una respuesta específicamente relacionada con los planes de consulta, pero hice un perfil de SP: StmtStarting y SP: StmtCompleted y mostró las llamadas a funciones.

Respuestas:


17

Y nada sobre las funciones. ¿Por qué falta la información de la función en el plan real?

Esto es por diseño, por razones de rendimiento.

Las funciones que contienen BEGINy ENDen la definición crean un nuevo marco de pila T-SQL para cada fila de entrada. Dicho de otra manera, el cuerpo de la función se ejecuta por separado para cada fila de entrada . Este hecho único explica la mayoría de los problemas de rendimiento asociados con las funciones escalares y de múltiples instrucciones de T-SQL (tenga en cuenta que las funciones con valores de tabla en línea no utilizan la BEGIN...ENDsintaxis).

En el contexto de su pregunta, esto daría como resultado una SHOWPLANsalida completa para cada fila. La producción del plan XML es bastante detallada y costosa de producir, por lo que producir una producción completa para cada fila sería una mala idea en términos generales.

Ejemplo

Considere la siguiente función escalar T-SQL, creada en la base de datos de ejemplo AdventureWorks , que devuelve el nombre de un producto dada su ID:

CREATE FUNCTION dbo.DumbNameLookup
(
    @ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
    RETURN
    (
        SELECT
            p.Name
        FROM Production.Product AS p
        WHERE
            p.ProductID = @ProductID
    );
END;

Plan de preejecución

Un plan previo a la ejecución (plan estimado en SSMS) muestra información del plan para la declaración principal y las llamadas de función anidadas:

-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;

Salida SSMS:

Plan de preejecución de SSMS

El mismo XML visto en SQL Sentry Plan Explorer muestra la naturaleza anidada de las llamadas más claramente:

Plan de preejecución de PE

Salida posterior a la ejecución

SSMS muestra detalles solo para la consulta principal cuando se solicita la salida del plan posterior a la ejecución:

-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;

SSMS post-ejecución

El impacto en el rendimiento de hacer lo contrario se puede mostrar usando la clase de evento Showplan XML Statistics Profile en SQL Server Profiler, usando una consulta que llama a la función varias veces (una vez por fila de entrada):

SELECT TOP (5)
    p.ProductID,
    dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;

Salida del perfilador:

Salida de rastreo

Hay cinco planes separados posteriores a la ejecución para las ejecuciones de funciones, y uno para la consulta principal. Los cinco planes de funciones se ven así en el panel inferior del generador de perfiles:

Planes de funciones

El plan de consulta principal es:

Plan de padres

La ejecución de la consulta sin la TOP (5)cláusula da como resultado un plan de ejecución completo para cada una de las 504 filas de la tabla Producto. Probablemente pueda ver cómo esto rápidamente se saldría de control con tablas más grandes.

La situación de los desencadenantes se invierte. Estos no muestran ninguna información del plan previo a la ejecución, pero sí incluyen un plan posterior a la ejecución. Esto refleja la naturaleza basada en conjuntos de los desencadenantes; cada uno se dispara una vez para todas las filas afectadas, en lugar de una vez por fila.


@PaulWhite, ¿hay alguna buena razón para que los planes de activación no se muestren al solicitar el plan de ejecución estimado? Parece una característica faltante útil. Podría crear un elemento de conexión para ello.
usr

@usr: ¿Tal vez porque el plan real en caché seleccionado puede variar dependiendo del número real de filas como se describe aquí? technet.microsoft.com/en-us/library/…
Martin Smith

@MartinSmith que podría ser una razón. Recientemente, un elemento de conexión para los planes de ejecución de las restricciones de verificación y fk se marcó como completado, por lo que esperaba que hicieran lo mismo con los desencadenantes.
usr

@ usr - ¿ Este aquí ? ¿3 meses? ¡Debe ser un cambio récord para una nueva solicitud de función!
Martin Smith

@ MartinSmith sí, ese. Fue "arreglado" hace un 1-2. Realmente espero no tener que consultar el almacén de consultas. Tenía la esperanza de hacer clic en un botón en SSMS. En realidad, me sorprendió ver algún cambio en una parte del motor que no se tocó en años. Pero tal vez no hubo ninguno.
usr
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.