de mauvaises performances avec sqlparameter
J'ai un web service, de sorte que le gestionnaire est appelé plusieurs fois simultanément tous les temps.
L'intérieur, j'ai créer SqlConnection et SqlCommand. J'ai à exécuter environ 7 les différentes commandes. Les différentes commandes nécessitent des différents paramètres, donc je viens de les ajouter une fois:
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));
Puis lors de l'exécution je viens de changer de CommandText prorerty et ensuite appeler la méthode ExecuteNonQuery(); ou ExecuteScalar();
Et je fais face à des problèmes de performances.
Par exemple peu de debuggin et de profilage de la montre, qui commande
command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = @UserID";
prend environ 50ms dans avarage. Si je le modifier:
command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = '" + userID.Replace("\'", "") + "'";
puis il prend seulement 1 ms dans avarage!
J'ai juste ne peux pas obtenir la moindre idée de l'endroit où étudier le problème.
userID
dans le C#, et quel est le type défini de la UserID
colonne dans la base de données?Êtes-vous sûr que c'est votre goulot d'étranglement des performances? Avez-vous profilée tout?
code d'utilisateur est une chaîne de caractères, en DB, il est de type varchar(20) est un PK
Eh bien, si j'ai coder en dur la déclaration de SSMS, profiler dit que c'est seulement 1ms. Puis-je enregistrer des horodateurs de code juste avant ExecuteNonQuery et juste après. Si j'utilise une chaîne direct, il est de 1ms, si j'utilise des param, il est 50ms. J'ai essayé de créer un sepearete objet de commande à séparer les param collecte et le résultat est le même.
pouvez-vous essayer explicitement la configuration du paramètre de type varchar? A C#
string
est unicode, donc (par défaut) les cartes de type nvarchar, pas de type varchar.OriginalL'auteur | 2011-12-21
Vous devez vous connecter pour publier un commentaire.
Qui sonne comme il a mis en cache une requête-plan pour un atypique
@UserID
valeur (un des premiers), et est la réutilisation d'un mauvais plan pour plus tard requêtes. Ce n'est pas un problème dans le deuxième cas, car chacun a un régime distinct. Je soupçonne que vous avez juste besoin d'ajouter:à la requête, à laquelle il sera moins envie de la ré-utilisation des plans à l'aveuglette.
Théorie Alternative:
Vous pourriez avoir un décalage entre le type de
userID
(en C#) et le type deUserID
(dans la base de données). Cela pourrait être aussi simple que d'unicode vs ANSI, ou pourrait êtreint
vsvarchar[n]
, etc. En cas de doute, être très spécifiques lors de la configuration du paramètre, ajouter avec les bons sous-type et de la taille.Clarification
En effet, il semble que le problème ici, c'est la différence entre un C#
string
(unicode) et de la base de données qui estvarchar(n)
(ANSI). LeSqlParameter
doit donc être explicitement ajouté en tant que tel (DbType.AnsiString
).WHERE
clause?si les données sont inégaux, oui; imaginez: la première requête s'exécute pendant un échantillon de l'utilisateur sans (ou très peu) de données - l'optimiseur de requête utilise les statistiques et décide sur un plan de requête optimisée pour les petits nombres de lignes. Cela explose alors extrêmement face à 200k lignes. J'ai vu des cas similaires, absolument. Seul moyen de le savoir est d'essayer avec et sans l'indice, si, p
Eh bien, c'est intéressant, j'ai sûrement étudier plus en détail. Nice lien est ici blogs.msdn.com/b/sqlprogrammability/archive/2008/11/26/... j'ai Donc essayé: SÉLECTIONNEZ LastShowTS DE LogForAllTime OÙ UserID = @UserID option (OPTIMISER POUR (@nom d'utilisateur INCONNU)) Aucun effet...
k; ce sujet de la deuxième partie ("théorie Alternative"), et le commentaire que j'ai ajouté pour vérifier certains détails?
serait la performance sera meilleure si la procédure stockée est utilisée à la place? c'est à dire., sans l'aide de
OPTION (OPTIMIZE FOR UNKNOWN)
OriginalL'auteur Marc Gravell
Vous êtes l'envoi de sept fois plus de données sur le serveur, de sorte qu'il sera plus lent.Aussi, si votre
userID
chaînes de longueurs différentes, le réglage d'une longueur explicite dans le paramètre SQL permet de le réutiliser la requête mieux.Êtes-vous adressant à mon, premier alinéa, ou mon second?
Première ligne - je ne voudrais pas s'attendre à ce que pour tenir compte de 50ms sauter. Peut-être de 0,1 ms d'écart (en supposant qu'aucun d'énormes valeurs).
J'ai essayé de paramètre séparé de collecte pour chaque commande - pas de changement significatif pour moi.
Oui, vous avez un point. (surtout depuis que son noms l'indiquent qu'ils ne sont pas des chaînes de caractères)
OriginalL'auteur SLaks