2010-08-17 19 views
10

Ho visto questo presentarsi diversi luoghi nel codice, non con una spiegazione, solo un commento criptico di sopra di essa (Dichiarazione e l'esecuzione inclusi per un'idea di contesto è solo una procedura standard di esecuzione di uno SqlCommand.):SqlCommand.Cancel() provoca un aumento delle prestazioni?

//SqlCommand cmd = new SqlCommand(); 
//cmd.ExecuteReader(); 
//Read off the results 

//Cancel the command. This improves query time. 
cmd.Cancel(); 

Fondamentalmente, dopo aver terminato una query, torna indietro e lo annulla, sostenendo un aumento delle prestazioni. Suppongo che potresti recuperare un po 'di memoria quando va e liberare XmlReader, ma di solito sta per uscire comunque.

Non mi sono mai preoccupato di farlo prima, ma alla fine è apparso in qualche codice che sto recensendo. Cancellare uno SqlCommand dopo averlo eseguito nel codice in qualche modo lo accelera, o è solo una strana superstizione del programmatore?

+0

Hai profilato il codice? Sarebbe interessante vedere quanti effetti ha effettivamente. – jloubert

+0

C'è un importante caso limite in cui chiamare Annulla fa una grande differenza - vedi la mia risposta sotto –

risposta

13

Secondo MSDN, questo è corretto.

Il primo metodo riempie i valori per i parametri di output, valori di ritorno e RecordsAffected, aumentando il tempo che ci vuole per chiudere uno SqlDataReader che è stato utilizzato per elaborare una grande o query complessa. Quando i valori ritorno e il numero dei record interessati da una query non sono significativo, il tempo che ci vuole per chiudere lo SqlDataReader può essere ridotta chiamando il metodo Cancel dell'oggetto SqlCommand associato prima chiamare il Chiudi metodo.

Strano!

+0

Huh. Non ho pensato di cercare nel documento SqlDataReader. Buona pesca! –

+1

Guardando il codice sottostante, è chiaro che fa una buona dose di lavoro su Chiudi, tuttavia, non immagino per un momento che questo sia tutto ciò che è significativo alla fine della giornata. –

+0

Imparato qualcosa ;-) Anche se sono d'accordo, dovresti essere seriamente colto da un collo di bottiglia su DB IO per notare la modifica. – gjvdkamp

0

Il nostro team tecnico di Cinchcast ha fatto un po 'di benchmarking, e abbiamo scoperto che l'aggiunta di cmd.Cancel() in realtà la rallenta.

Abbiamo una chiamata DALC che ottiene un elenco di episodi per un host. L'abbiamo eseguito 1000 volte e ottenuto il tempo medio di risposta per restituire 10 episodi.

Quindi, con il ritorno di 10 spettacoli media Con Cancellare: 0.069s media Senza Annulla: 0.026s

Piuttosto significativamente più lento quando si esegue con il ritorno 10 episodio.

Quindi, ho provato di nuovo a restituire 100 episodi per vedere se un set di risultati più grande fa la differenza.

Quindi, con il ritorno di 100 spettacoli per ogni chiamata media Con Cancellare: 0.132s media Senza Annulla: 0.122s

Così questa volta la differenza di tempo era molto meno. È ancora più veloce anche se non si utilizza Annulla per i nostri casi di utilizzo abituali.

7

Calling Cancel dà un potenziale miglioramento delle prestazioni MASSIVE se la vostra chiamata a ExecuteReader restituisce un gran numero di righe, e si non leggere tutte le righe.

Per illustrare, diciamo che una query restituisce un milione di righe e si chiude il lettore dopo aver letto solo le prime 1000 righe. Se non si riesce a chiamare Cancel prima di chiudere il lettore, il metodo Close sarà blocco mentre enumera internamente attraverso i rimanenti 999.000 righe

Provare per credere!

+0

Non può essere troppo sottostimato quanto il "Non leggere tutte le righe" è la funzione principale di questo metodo. – JJS

0

Nel tuo esempio, apri il lettore, leggi tutte le righe e Annulla il comando, ma non hai mostrato dove il lettore veniva chiuso.

Assicurarsi che l'annullamento avvenga prima del il Dispose/Close. Ad esempio, non si otterrebbe un incremento delle prestazioni in questo esempio (codice reale in produzione, purtroppo):

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default)) 
{ 
    retval = DocumentDir.DBRead (rdr); 
} 

// Optimization. Allows reader to close more quickly.... NOT! 
cmd.Cancel(); // bad! 

Peccato che sia già chiuso dalla dichiarazione Utilizzando!

Ecco come dovrebbe leggere per realizzare il potenziale beneficio:

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default)) 
{ 
    retval = DocumentDir.DBRead (rdr); 

    // Optimization. Allows reader to close more quickly. 
    cmd.Cancel(); 
} 

Da MSDN SqlCommand.Cancel:

In alcuni, rari, casi, se si chiama ExecuteReader quindi chiamare Chiudi (implicitamente o esplicitamente) prima di chiamare Annulla, quindi chiamare Annulla, il comando annulla non verrà inviato a SQL Server e il set di risultati può continuare a trasmettere dopo aver chiamato Chiudi. Per evitare ciò, assicurarsi di chiamare Annulla prima di chiudere il lettore o la connessione.

Problemi correlati