SqlDataAdapter.Fill metodo lento

Perché una stored procedure che restituisce una tabella con 9 colonne, 89 righe utilizzando questo codice impiega 60 secondi per eseguire (.NET 1.1) quando impiega <1 secondo per l'esecuzione in SQL Server Management Studio? È in esecuzione sulla macchina locale, quindi poca / nessuna latenza di rete, veloce macchina di sviluppo

Dim command As SqlCommand = New SqlCommand(procName, CreateConnection()) command.CommandType = CommandType.StoredProcedure command.CommandTimeout = _commandTimeOut Try Dim adapter As new SqlDataAdapter(command) Dim i as Integer For i=0 to parameters.Length-1 command.Parameters.Add(parameters(i)) Next adapter.Fill(tableToFill) adapter.Dispose() Finally command.Dispose() End Try 

il mio array di parametri viene digitato (per questo SQL è solo un singolo parametro)

 parameters(0) = New SqlParameter("@UserID", SqlDbType.BigInt, 0, ParameterDirection.Input, True, 19, 0, "", DataRowVersion.Current, userID) 

La stored procedure è solo un’istruzione select in questo modo:

 ALTER PROC [dbo].[web_GetMyStuffFool] (@UserID BIGINT) AS SELECT Col1, Col2, Col3, Col3, Col3, Col3, Col3, Col3, Col3 FROM [Table] 

Innanzitutto, assicurati di profilare correttamente le prestazioni. Ad esempio, eseguire la query due volte da ADO.NET e vedere se la seconda volta è molto più veloce della prima volta. Ciò elimina il sovraccarico di attesa per la compilazione dell’app e l’espansione dell’infrastruttura di debug.

Quindi, controllare le impostazioni predefinite in ADO.NET e SSMS. Ad esempio, se si esegue SET ARITHABORT OFF in SSMS, è ansible che ora venga eseguito lento come quando si utilizza ADO.NET.

Quello che ho trovato una volta è stato che SET ARITHABORT OFF in SSMS ha causato la ricompilazione del processo memorizzato e / o l’utilizzo di statistiche diverse. E all’improvviso sia SSMS che ADO.NET riportavano all’incirca lo stesso tempo di esecuzione.

Per verificare ciò, esaminare i piani di esecuzione per ogni esecuzione, in particolare la tabella syscacheobjects. Probabilmente saranno diversi.

L’esecuzione di “sp_recompile” su una stored procedure specifica farà cadere il piano di esecuzione associato dalla cache, il che darà a SQL Server la possibilità di creare un piano eventualmente più appropriato alla successiva esecuzione della procedura.

Infine, puoi provare l’approccio ” nuke it orbit ” per pulire l’intera cache della procedura e i buffer di memoria usando SSMS:

 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE 

Farlo prima di testare la tua query impedisce l’utilizzo di piani di esecuzione memorizzati nella cache e cache dei risultati precedenti.

Ecco cosa ho finito per fare:

Ho eseguito la seguente istruzione SQL per ribuild gli indici su tutte le tabelle nel database:

 EXEC ..sp_MSforeachtable @command1='DBCC DBREINDEX (''*'')', @replacechar='*' -- Replace  with the name of your database 

Se volevo vedere lo stesso comportamento in SSMS, ho eseguito il proc in questo modo:

 SET ARITHABORT OFF EXEC [dbo].[web_GetMyStuffFool] @UserID=1 SET ARITHABORT ON 

Un altro modo per aggirare questo è aggiungere questo al tuo codice:

 MyConnection.Execute "SET ARITHABORT ON" 

Mi sono imbattuto nello stesso problema, ma quando ho ricostruito gli indici sulla tabella SQL, ha funzionato bene, quindi potresti prendere in considerazione la possibilità di ribuild l’indice sul lato sql server

Perché non renderlo un DataReader invece di DataAdapter, sembra che tu abbia un set di risultati singel e se non stai andando a spingere le modifiche indietro nel DB e non hai bisogno di vincoli applicati nel codice .NET che non dovresti usare l’adattatore.

MODIFICARE:

Se è necessario che sia un DataTable, è comunque ansible estrarre i dati dal DB tramite un DataReader e quindi nel codice .NET utilizzare DataReader per popolare un DataTable. Questo dovrebbe essere ancora più veloce che affidarsi a DataSet e DataAdapter

Ho avuto lo stesso problema e ho risolto il problema utilizzando questo articolo: http://www.databasejournal.com/features/mssql/article.php/3841271/T-SQL-Best-Practices–Parameter-Sniffing.htm

Non so “Perché” è così lento di per sé – ma come fa notare Marcus – il confronto tra Mgmt Studio e il riempimento di un set di dati è rappresentato dalle mele alle arance. I set di dati contengono MOLTO sovraccarico. Li odio e non li uso MAI se posso aiutarlo.

Potresti avere problemi con la mancata corrispondenza delle vecchie versioni dello stack SQL o alcuni di questi (specialmente se sei ovviamente bloccato in .NET 1.1). Probabilmente il Framework sta cercando di creare un database equivoco di “Reflection” per inferire lo schema ecc. Ecc. Ecc.

Una cosa da considerare, provare con il tuo sfortunato vincolo è accedere al database con un datareader e creare il proprio set di dati nel codice. Dovresti riuscire a trovare campioni facilmente tramite google.