2011-12-02 12 views
5

Utilizzando MSSQL 2005UDF vs prestazioni di SQL diretto

stavo giocando in giro oggi con uno scalare UDF in un comunicato in cui per vedere alcuni dei costi associati di effettuare la chiamata e IO differenze ecc

I' m iniziando con 2 tavoli base. Cliente che ha 1 milione di righe. e gli acquisti che ha 100.000. Entrambi hanno una colonna di identità automatica come chiave primaria. Nessun altro indice definito.

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 

Questo restituisce le statistiche IO di

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. 

Quindi, solo per vedere l'impatto di un'UDF scalare Ho poi appena spostato il P.Amount> 1000 ad un'UDF. La funzione è la seguente:

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 

Così ho poi corse la seguente query:

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 

mi aspettavo questo per funzionare peggio. Questa query ha restituito le seguenti statistiche 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. 

Questo anche restituito più veloce del> 1000 query. Mentre venivano restituite le stesse righe, l'ordinamento di quella che chiamava l'UDF veniva automaticamente ordinato da C. [IDENTITY] dove l'altra query appariva non ordinata. Ciò è probabilmente dovuto al modo in cui le mietitrebbie sono state eseguite nei piani di esecuzione. Il profilo dei piani è sotto.

Il piano di esecuzione per la non UDF mostra una scansione indice cluster per acquisti e un indice cluster ricerca per clienti combinati a un join nidificato.

Il piano di esecuzione per la versione UDF mostra una scansione dell'indice cluster per gli acquisti, quindi un filtro, quindi un ordinamento. C'è una scansione indice raggruppata sul cliente. Quindi i risultati vengono combinati in Unisci join.

Sono sicuro che questo ha a che fare con la mancanza di indici, ecc., Ma non sono sicuro del perché questi risultati siano così come sono. Ho sperimentato la corsa di UDF dolorosamente lenta e tutti dicono che usarli di solito è una cattiva idea, motivo per cui ho lanciato questo test insieme. Al momento non posso spiegare perché la versione UDF sembra essere molto meglio.

+0

Abbiamo trovato alcune informazioni relative a questo: http://sqlinthewild.co.za/index.php/2009/04/29/functions-io-statistics-and-the-execution-plan/ I still can ' t ottenere le statistiche IO "reali" per la query sopra, ma questo almeno aiuta a spiegarlo. – Equixor

+0

Non sembra che tu abbia una risposta su questo forum. Potrebbe voler pubblicare su un sito più sql specifico. vale a dire. http://www.sqlservercentral.com/Forums/ –

+0

perché mai dovresti nominare una colonna IDENTITY ??? perché non nominarlo CustomerID in entrambe le tabelle ??? nominare cose come questa uccide la prossima povera persona che dovrà lavorare su questo sistema dopo di te. –

risposta

1
  • Se si desidera partecipare su Purchases.CustomerID si dovrebbe mettere un indice su di esso.
  • Se si esegue spesso query su intervalli di valori, è necessario inserire anche un indice.

Così come si sta chiedendo al server SQL di scegliere tra due piani non validi.

SQL Server può indovinare approssimativamente quanti acquisti saranno coperti dalla query > 1000 e selezionerà un piano basato su tale.

Tuttavia non è possibile indovinare quanti saranno coperti dalla query UDF, quindi è possibile selezionare un piano diverso. Poiché sta andando nell'ignoranza, potrebbe essere migliore o peggiore dell'altro piano, a seconda di quanto sia buona l'ipotesi.

È possibile visualizzare i piani generati e verrà indicato il numero stimato di righe in ciascun piano e anche il numero effettivo. Questi numeri stimati rappresentano la scelta del piano in ciascun caso.

Problemi correlati