2009-08-07 14 views
7

Estoy reescribiendo algún procedimiento almacenado anterior y he encontrado un problema de rendimiento inesperado cuando uso una función en lugar de un código en línea.Por qué una función T-SQL UDF simple hace que la ejecución del código sea 3 veces más lenta

La función es muy simple de la siguiente manera:

ALTER FUNCTION [dbo].[GetDateDifferenceInDays] 
(  
@first_date SMALLDATETIME, 
@second_date SMALLDATETIME 
) 
RETURNS INT 
AS 
BEGIN 

RETURN ABS(DATEDIFF(DAY, @first_date, @second_date)) 

END 

así que tengo dos consultas idénticas, pero se utiliza la función y el otro hace el cálculo en la propia consulta:

ABS(DATEDIFF(DAY, [mytable].first_date, [mytable].second_date)) 

Ahora la consulta con el código en línea se ejecuta 3 veces más rápido que el que usa la función.

Respuesta

14

Lo que tiene es una UDF escalar (toma de 0 a n parámetros y devuelve un valor escalar). Dichas UDF generalmente causan una operación fila por fila de su consulta, a menos que se invoque con parámetros constantes, exactamente con el tipo de degradación de rendimiento que experimenta con su consulta.

Consulte here, here y here para obtener explicaciones detalladas de las dificultades de rendimiento al usar UDF.

+0

Gracias por publicar. Su último enlace es un buen análisis empírico sobre este problema, pero no explica por qué es este comportamiento. –

+1

@nagul: su primer enlace es malo. Parece que SQLMag cambió su URL. ¿Hay alguna posibilidad de que este sea el artículo? http://sqlmag.com/user-defined-function-udf/udfs-endanger-performance – EBarr

5

Dependiendo del contexto de uso, el optimizador de consultas puede analizar el código en línea y descubrir un gran plan de consulta que utiliza índices, mientras que no "alinea la función" para un análisis detallado similar y termina así con un plan de consulta inferior cuando la función está involucrada. ¡Mira los dos planes de consulta, uno al lado del otro, y deberías poder confirmar (o refutar) esta hipótesis con bastante facilidad!

+0

Gracias por publicar. Analicé los dos planes de ejecución y son idénticos, excepto que el que no usa UDF escalares tiene "paralelismo" antes de ejecutar Bucles anidados (3 ocurrencias). Sé que el paralelismo mejora el tiempo de ejecución ya que aprovecha múltiples procesadores; pero ¿debo asumir que todo es causado por la falta de paralelismo en el plan de ejecución? –

13

No utilice un UDF escalar lento, use uno rápido en línea. Los ejemplos aquí:

Reuse Your Code with Table-Valued UDFs

Calculating third Wednesday of the month with inline UDFs

Many nested inline UDFs are very fast

La pregunta es muy común: se ha preguntado y contestado cientos de veces antes, como tal, tiene algunas respuestas enlatadas.

+1

Quien haya votado negativamente, proporcione el motivo. –

+1

@Alex: Tu publicación también se ha marcado como spam, así que supongo que alguien (¡y no yo!) Cree que estás enviando enlaces a tu blog en lugar de responder a la pregunta. – RichieHindle

+2

Si los enlaces responden a la pregunta, no importa si provienen del propio blog del póster. Déjalo obtener algo de jugo de Google. No es como si estuviera vendiendo suscripciones a revistas. Es un buen blog; mi suposición es que el indicador ni siquiera lo miró. –

Cuestiones relacionadas