Низкая производительность с 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 позволит лучше повторно использовать запрос.

Другие вопросы по тегам