низкая производительность с sqlparameter - PullRequest
9 голосов
/ 21 декабря 2011

У меня есть веб-сервис, поэтому обработчик вызывается несколько раз одновременно.

Внутри я создаю 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 и затем вызываю ExecuteNonQuery (); или ExecuteScalar ();

И я столкнулся с проблемой производительности. Например, небольшая отладка и профилирование показывают, что команда

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

занимает около 50 мс в среднем. Если я изменю это на:

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

тогда в среднем это займет всего 1 мс!

Я просто не могу понять, где исследовать проблему.

Ответы [ 2 ]

15 голосов
/ 21 декабря 2011

Звучит так, как будто он кэшировал план запроса для нетипичного значения @UserID (одно из ранних) и повторно использует плохой план для последующих запросов.Это не проблема во втором случае, так как у каждого есть отдельный план.Я подозреваю, что вам просто нужно добавить:

OPTION (OPTIMIZE FOR UNKNOWN)

к запросу, что уменьшит желание повторного использования планов вслепую.


Альтернативная теория:

Возможно, имеется несоответствие между типом userID (в C #) и типом UserID (в базе данных).Это может быть просто Unicode против ANSI или int против varchar[n] и т. Д. Если вы сомневаетесь, при настройке параметра укажите очень специфичный , чтобы добавить его с правильным подтипоми размер.

Пояснение

Действительно, похоже, что проблема здесь в том, что разница между C # string (Unicode) и базой данных составляет varchar(n) (ANSI).Поэтому SqlParameter должно быть явно добавлено как таковое (DbType.AnsiString).

0 голосов
/ 21 декабря 2011

Вы отправляете на сервер в семь раз больше данных, поэтому это будет медленнее.

Кроме того, если строки userID имеют разную длину, установите явную длину впараметр SQL позволит лучше повторно использовать запрос.

...