2011-12-21 17 views
8

Ho un servizio Web, quindi il gestore viene chiamato più volte contemporaneamente in modo continuo.prestazioni scarse con sqlparameter

All'interno creo SqlConnection e SqlCommand. Devo eseguire circa 7 diversi comandi. Diversi comandi richiedono vari parametri, quindi è sufficiente aggiungere una volta:

command.Parameters.Add(new SqlParameter("@UserID", userID)); 
command.Parameters.Add(new SqlParameter("@AppID", appID)); 
command.Parameters.Add(new SqlParameter("@SID", SIDInt)); 
command.Parameters.Add(new SqlParameter("@Day", timestamp.Date)); 
command.Parameters.Add(new SqlParameter("@TS", timestamp)); 

Poi durante l'esecuzione mi basta cambiare CommandText prorerty e quindi chiamare ExecuteNonQuery(); o ExecuteScalar();

E ho riscontrato problemi di prestazioni. Per esempio debuggin e profilatura piccoli spettacoli, detto ordine

command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = @UserID"; 

prende circa 50ms in avarage. Se lo cambio a:

command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = '" + userID.Replace("\'", "") + "'"; 

allora ci vogliono solo 1ms in fuochi d'artificio!

Non riesco proprio a capire dove indagare il problema.

+1

Puoi indicare: qual è il tipo definito di 'userID' nel C# e qual è il tipo definito della colonna' UserID' nel database? –

+0

Sei sicuro che questo è il collo di bottiglia delle tue prestazioni? Hai profilato tutto? – asawyer

+0

userID è una stringa, in DB è varchar (20) ed è un PK –

risposta

13

Sembra che abbia memorizzato nella cache un piano di query per un valore atipico @UserID (uno dei primi) e sta riutilizzando un piano scadente per le query successive. Questo non è un problema nel secondo caso poiché ognuno ha un piano separato. Ho il sospetto che basta aggiungere:

OPTION (OPTIMIZE FOR UNKNOWN) 

alla query, che renderà meno desiderosi di riutilizzare piani ciecamente.


teoria alternativa:

Si potrebbe avere una mancata corrispondenza tra il tipo di userID (in C#) e il tipo di UserID (nel database). Questo potrebbe essere semplice come unicode vs ANSI, o potrebbe essere rispetto a varchar[n], ecc. In caso di dubbio, è molto specifico quando si configura il parametro, per aggiungerlo con il sottotipo e la dimensione corretti.

Chiarimento

In effetti, sembra che il problema qui è la differenza tra un C# string (Unicode) e il database che è varchar(n) (ANSI). Il SqlParameter dovrebbe quindi essere esplicitamente aggiunto come tale (DbType.AnsiString).

+0

Questo farebbe davvero la differenza per una semplice clausola 'WHERE'? – SLaks

+0

@SLaks se i dati non sono uniformi, sì; Immagina: la prima query viene eseguita per un utente di esempio senza dati (o molto poco) - Query Optimizer utilizza le statistiche e decide su un piano di query ottimizzato per un numero limitato di righe. Questo poi esplode enormemente di fronte a 200k righe. Ho visto casi simili, assolutamente. L'unico modo per scoprirlo è provarlo con e senza il suggerimento, però: p –

+0

Bene, questa è una caratteristica interessante che sicuramente indagherò in modo più dettagliato. Il link giusto è qui http://blogs.msdn.com/b/sqlprogrammability/archive/2008/11/26/optimize-for-unknown-a-little-known-sql-server-2008-feature.aspx Quindi ho provato: LastShowTS selezionare dalla LogForAllTime WHERE UserID = @UserID opzione (Ottimizza per (@UserID UNKNOWN)) Nessun effetto ... –

0

Stai inviando sette volte più dati al server, quindi sarà più lento.

Inoltre, se le stringhe userID hanno lunghezze diverse, l'impostazione di una lunghezza esplicita nel parametro SQL consentirà di riutilizzare meglio la query.

+0

Che non calcola; ciò si applicherebbe solo se i parametri fossero enormi e che i problemi di larghezza di banda fossero il collo di bottiglia; Dubito molto che questo sia il caso qui. Il tempo per inviare alcuni parametri di base è banale, e ampiamente superato dalla latenza (piuttosto che dalla larghezza di banda) nella maggior parte dei casi. –

+0

@MarcGravell: stai affrontando il mio primo paragrafo o il mio secondo? – SLaks

+0

Prima riga: non mi aspetto che ciò tenga conto di un salto di 50 ms. Forse una deviazione di 0.1ms (non assumendo valori enormi). –

Problemi correlati