Низкая производительность с sqlparameter
У меня есть веб-сервис, поэтому обработчик вызывается несколько раз одновременно.
Внутри я создаю SqlConnection и SqlCommand. Я должен выполнить около 7 разных команд. Разные команды требуют разных параметров, поэтому я просто добавляю их один раз:
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));
Затем во время выполнения я просто изменяю CommandText prorerty и затем вызываю ExecuteNonQuery(); или ExecuteScalar();
И я сталкиваюсь с проблемой производительности. Например, маленькая отладка и профилирование показывает, что команда
command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = @UserID";
занимает около 50 мс в среднем. Если я изменю это на:
command.CommandText = "SELECT LastShowTS FROM LogForAllTime WHERE UserID = '" + userID.Replace("\'", "") + "'";
тогда это занимает всего 1 мс в среднем!
Я просто не могу понять, где исследовать проблему.
2 ответа
Похоже, что он кэшировал план запроса для нетипичного @UserID
значение (один из первых), и повторно использует плохой план для последующих запросов. Это не проблема во втором случае, так как у каждого есть отдельный план. Я подозреваю, что вам просто нужно добавить:
OPTION (OPTIMIZE FOR UNKNOWN)
на запрос, который сделает менее заинтересованным повторное использование планов вслепую.
Альтернативная теория:
У вас может быть несоответствие между типом userID
(в C#) и тип UserID
(в базе данных). Это может быть так же просто, как Unicode против ANSI, или может быть int
против varchar[n]
и т. д. Если вы сомневаетесь, будьте очень точны при настройке параметра, чтобы добавить его с правильным подтипом и размером.
осветление
Действительно, похоже, что проблема здесь в том, что разница между C# string
(Unicode) и база данных, которая является varchar(n)
(ANSI). SqlParameter
поэтому должен быть явно добавлен как таковой (DbType.AnsiString
).
Вы отправляете на сервер в семь раз больше данных, поэтому это будет медленнее.
Кроме того, если ваш userID
Строки имеют разную длину, установка явной длины в параметре SQL позволит лучше повторно использовать запрос.