Могу ли я остановить вызов sp_reset_connection для повышения производительности?
Моя трассировка профилировщика показывает, что exec sp_reset_connection
вызывается между каждым вызовом sql или вызовом процедуры. Есть причины , но могу ли я предотвратить его вызов, если я уверен, что это лишнее, для повышения производительности?
UPDATE:
Причина, по которой я предполагаю, что это может улучшить производительность, двояка:
- SQL Server не нуждается в состоянии подключения reset. Я думаю, что это будет относительно незначительное улучшение.
- Уменьшенная латентность сети, потому что клиенту не нужно отправлять
exec sp_reset_connection
, ждать ответа, а затем отправлять любой SQL-код, который он действительно хочет выполнить.
Второе преимущество - это то, что меня интересует, потому что в моей архитектуре клиенты иногда находятся на некотором расстоянии от базы данных. Если для каждой sql-партии или rpc требуется двойное округление, это удваивает влияние любой латентности сети. Устранение таких двойных вызовов может потенциально повысить производительность.
Да, есть много других вещей, которые я мог бы сделать, чтобы улучшить производительность, например, перепроектировать приложение, и я большой поклонник решения основной причины проблем, но в этом случае я просто хочу знать, возможно ли это для предотвращения вызова sp_reset_connection. Затем я могу проверить, есть ли какие-либо улучшения производительности и правильно оценить риски, не вызвав этого.
Это вызывает другой вопрос: действительно ли сетевое общение с sp_reset_connection происходит, как описано выше? Т.е. клиент отправляет exec sp_reset_connection
, ждет ответа, а затем отправляет реальный sql? Или все это входит в один кусок?
Ответы
Ответ 1
Если вы используете .NET для подключения к SQL Server, отключение дополнительного вызова reset было отключено как .NET 3.5 - см. здесь. (Свойство остается, но ничего не делает.)
Я предполагаю, что Microsoft поняла (как кто-то экспериментировал здесь), что открытие двери во избежание reset было намного опаснее, чем было получить (вероятно ) небольшой прирост производительности. Не могу сказать, что я их виню.
Клиент отправляет exec sp_reset_connection
, ждет ответа, а затем отправляет реальный sql?
EDIT: Я ошибся - см. здесь - ответ - нет.
Сводка: в сообщении TDS есть специальный бит, который указывает, что соединение должно быть reset, а SQL Server автоматически выполняет sp_reset_connection
. Он появляется как отдельная партия в Profiler и всегда будет выполняться до фактического запроса, который вы хотели выполнить, поэтому мой тест был недействительным.
Да, он отправляется в отдельной партии.
Я собрал небольшую пробную программу С#, чтобы продемонстрировать это, потому что мне было любопытно:
using System.Data.SqlClient;
(...)
private void Form1_Load(object sender, EventArgs e)
{
SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
csb.DataSource = @"MyInstanceName";
csb.IntegratedSecurity = true;
csb.InitialCatalog = "master";
csb.ApplicationName = "blarg";
for (int i = 0; i < 2; i++)
_RunQuery(csb);
}
private void _RunQuery(SqlConnectionStringBuilder csb)
{
using (SqlConnection conn = new SqlConnection(csb.ToString()))
{
conn.Open();
SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:05'", conn);
cmd.ExecuteNonQuery();
}
}
Запустите Профилировщик и прикрепите его к выбранному вами экземпляру, отфильтровав имя фиктивного приложения, которое я предоставил. Затем положите точку останова на строку cmd.ExecuteNonQuery();
и запустите программу.
В первый раз, когда вы переходите, просто выполняется запрос, и все, что вы получаете, - это событие SQL: BatchCompleted после 5 секунд ожидания. Когда точка останова попадает во второй раз, все, что вы видите в профилировщике, по-прежнему остается единственным событием. Когда вы переходите снова, вы сразу видите событие exec sp_reset_connection
, а затем после задержки появляется событие SQL: BatchCompleted.
удаp >
Единственный способ избавиться от вызова exec sp_reset_connection
(который может или не может быть законной проблемой производительности для вас) - это отключить пул соединений .NET. И если вы планируете это сделать, вы, скорее всего, захотите создать свой собственный механизм объединения пулов, потому что просто отключить его и ничего не делать больше, возможно, повредит больше, чем ударить по лишнему кругообороту, и у вас будет для решения проблем корректности вручную.
Ответ 2
Лично я оставил бы его.
Учитывая то, что он делает, я хочу убедиться, что у меня нет временных таблиц в области видимости или транзакций, открытых.
Чтобы быть справедливым, вы получите большее повышение производительности, не запуская профилировщик против вашей производственной базы данных. И есть ли у вас какие-либо цифры или статьи или рекомендации о том, что вы можете получить от этого, пожалуйста?
Ответ 3
Этот Q/A может быть полезен:
Что такое "exec sp_reset_connection" в Sql Server Profiler?
Однако, я быстро проверил использование Entity Framework и MS-SQL 2008 R2. Он показывает, что "exec sp_reset_connection" не занимает много времени после первого вызова:
for (int i = 0; i < n; i++)
{
using (ObjectContext context = new myEF())
{
DateTime timeStartOpenConnection = DateTime.Now;
context.Connection.Open();
Console.WriteLine();
Console.WriteLine("Opening connection time waste: {0} ticks.", (DateTime.Now - timeStartOpenConnection).Ticks);
ObjectSet<myEntity> query = context.CreateObjectSet<myEntity>();
DateTime timeStart = DateTime.Now;
myEntity e = query.OrderByDescending(x => x.EventDate).Skip(i).Take(1).SingleOrDefault<myEntity>();
Console.Write("{0}. Created By {1} on {2}... ", e.ID, e.CreatedBy, e.EventDate);
Console.WriteLine("({0} ticks).", (DateTime.Now - timeStart).Ticks);
DateTime timeStartCloseConnection = DateTime.Now;
context.Connection.Close();
context.Connection.Dispose();
Console.WriteLine("Closing connection time waste: {0} ticks.", (DateTime.Now - timeStartCloseConnection).Ticks);
Console.WriteLine();
}
}
И результат был следующим:
Отключить время соединения: 5390101. 585. Создано sa 12/20/2011 2:18:23 PM... (2560183 тика). Задержка закрытия соединения: 0 тиков.
Время открытия соединения: 0 тиков. 584. Создано sa 12/20/2011 2:18:20 PM... (1730173 тиков). Задержка закрытия соединения: 0 тиков.
Время открытия соединения: 0 тиков. 583. Создано sa 12/20/2011 2:18:17 PM... (710071 тиков). Задержка закрытия соединения: 0 тиков.
Время открытия соединения: 0 тиков. 582. Создано sa 12/20/2011 2:18:14 PM... (720072 клещей). Задержка закрытия соединения: 0 тиков.
Время открытия соединения: 0 тиков. 581. Создано sa 12/20/2011 2:18:09 PM... (740074 тика). Задержка закрытия соединения: 0 тиков.
Итак, окончательный вывод: не беспокойтесь о "exec sp_reset_connection"! Он ничего не теряет.
Ответ 4
Просто держите соединение открытым, а не возвращайте его в пул, и выполните все команды в этом соединении.