2011-12-02 19 views
5

Usando MSSQL 2005UDF vs rendimiento de SQL directa

Yo estaba jugando hoy con un escalar UDF en un comunicado, donde para ver algunos de los costos asociados con la fabricación de la llamada y io diferencias etc.

I' m comenzando con 2 tablas básicas. Cliente que tiene 1 millón de filas. y compras que tiene 100,000. Ambos tienen una columna de identidad automática como clave principal. No hay otros índices definidos.

DBCC FREEPROCCACHE 
DBCC DROPCLEANBUFFERS 

SET STATISTICS IO ON 
    SELECT * FROM Customer C 
    INNER JOIN Purchases P on C.[IDENTITY] = P.CustomerID 
    WHERE P.Amount > 1000 
SET STATISTICS IO OFF 

Esto devuelve las estadísticas de IO

Table 'Customer'. Scan count 0, logical reads 3295, physical reads 1, read-ahead reads 32, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Purchases'. Scan count 1, logical reads 373, physical reads 1, read-ahead reads 370, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

lo tanto, sólo para ver el impacto de una UDF escalar Entonces acabo de mudar el P.Amount> 1000 a una UDF. Función es la siguiente:

CREATE FUNCTION [dbo].[HighValuePurchase] 
(
    @value int 
) 
RETURNS bit 
AS 
BEGIN 
    DECLARE @highValue bit 
    SET @highValue = '0' 

    IF @value > 1000 
    BEGIN 
     SET @highValue = '1' 
    END 
    RETURN @highValue 
END 

Así que corrió la siguiente consulta:

DBCC FREEPROCCACHE 
DBCC DROPCLEANBUFFERS 

SET STATISTICS IO ON  
    SELECT * FROM Customer C 
    INNER JOIN Purchases P on C.[IDENTITY] = P.CustomerID 
    WHERE dbo.HighValuePurchase(P.Amount) = '1' 
SET STATISTICS IO OFF 

me esperaba esto para ejecutar peor. Esta consulta devuelve los siguientes estadísticas IO:

Table 'Purchases'. Scan count 1, logical reads 373, physical reads 1, read-ahead reads 370, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Customer'. Scan count 1, logical reads 35, physical reads 3, read-ahead reads 472, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

Esto también volvieron más rápido que la> 1000 consulta. Mientras se devolvían las mismas filas, el orden del que llamaba a la UDF se ordenaba automáticamente por C. [IDENTIDAD], donde la otra consulta no estaba ordenada. Esto probablemente se deba a la forma en que se hicieron las combinaciones en los planes de ejecución. El esquema de los planes está a continuación.

El plan de ejecución para el UDF no muestra un análisis de índice agrupado para compras y una búsqueda de índice agrupado para clientes combinados en una combinación anidada.

El plan de ejecución para la versión UDF muestra un análisis de índice agrupado para compras, luego un filtro y luego un ordenamiento. Hay un escaneo indexado agrupado en el cliente. Luego, los resultados se combinan en una combinación de combinación.

Estoy seguro de que esto tiene que ver con la falta de índices, etc., pero no estoy seguro de por qué estos resultados son los que son. Experimenté que la UDF funcionaba con lentitud y todos dicen que usarlas generalmente es una mala idea, y es por eso que hice esta prueba juntos. No puedo explicar por qué la versión UDF parece ser mucho mejor.

+0

Encontré algo de información relacionada con esto: http://sqlinthewild.co.za/index.php/2009/04/29/functions-io-statistics-and-the-execution-plan/ Todavía puedo ' Obtenga las estadísticas de IO "verdaderas" para la consulta anterior, pero esto al menos ayuda a explicarlo. – Equixor

+0

Parece que no va a obtener una respuesta en este foro. Es posible que desee publicar en un sitio específico más sql. es decir. http://www.sqlservercentral.com/Forums/ –

+0

¿por qué demonios nombrarías una columna IDENTIDAD? ¿por qué no solo nombrarlo CustomerID en ambas tablas? nombrar cosas como esta simplemente mata a la próxima persona pobre que tendrá que trabajar en este sistema después de ti. –

Respuesta

1
  • Si quieres unirte a Purchases.CustomerID debes poner un índice sobre él.
  • Si consulta con frecuencia en rangos de valores también debe poner un índice sobre eso.

Como le está pidiendo al servidor SQL que elija entre dos planes incorrectos.

SQL Server puede adivinar aproximadamente cuántas compras se cubrirán con la consulta > 1000, y elegirá un plan basado en eso.

Sin embargo, no puede adivinar cuántos cubrirá la consulta UDF, por lo que puede elegir un plan diferente. Debido a que está pasando por ignorancia, podría ser mejor o peor que el otro plan, dependiendo de qué tan bueno sea.

Puede ver los planes generados y le indicará el número estimado de filas en cada plan, y también el número real. Esos números estimados representan la elección del plan en cada caso.