Время выполнения замедляется с каждой итерацией одного и того же SPROC

Запуск той же хранимой процедуры из приложения C#.Net по сети становится все медленнее с каждое последующее исполнение. Похоже, что это занимает в два раза больше времени, чем предыдущее выполнение (до максимального значения; читайте дальше). Время выполнения становится все медленнее, пока не произойдет 1 из 2 сценариев, после чего первое выполнение SPROC снова становится «быстрым».

  1. Если SqlConnectionоткрыт и остается открытым во время всех испытаний, SPROC становится все медленнее, пока не будет запущен любой другой SPROC или запрос .
  2. Если SqlConnectionоткрывается и закрывается при каждом выполнении, SPROC становится все медленнее, пока не пройдет не менее 8 минут .

Это происходит только с несколькими хранимыми процедурами. Один из них — простой SELECTзапрос с 2 JOINs,(SPROC 1 ), другой — массивный 1600+ строк SPROC(SPROC 2).

Время выполнения никогда не выходит за пределы ровно 60 секунд для SPROC 1 и 67 секунд для SPROC 2 . SPROC 1 первоначально выполняется менее чем за секунду, а SPROC 2 первоначально занимает 7 секунд.

Это также происходит, только если SPROC запускается с использованием того же SqlConnectionв приложении. Как только используются 2 отдельных объекта SqlConnection, они ведут себя так же, как указано выше, но являются независимыми. Многократный запуск SPROC на SqlConnection1становится все медленнее, но при первом запуске одного и того же SPROC на SqlConnection2он «быстрый». Затем он также будет замедляться при многократном запуске на SqlConnection2.

Этого не происходит, если приложение запущено на том же компьютере с установленным SQL Server 2008 R2 (под управлением Windows Server 2008). Время выполнения всегда стабильно.

Запуск хранимой процедуры из Management Studio также не замедляется с каждым запуском; это всегда последовательно.

Очистка кэша планов выполнения (в SQL Server)не влияет на наблюдаемое поведение.

Потребовалось несколько дней, чтобы сузить круг этой проблемы, первоначально обнаруженной в гораздо более крупном приложении, и создать тестовое приложение, чтобы легко протестировать/воспроизвести ее.

Из того, что я прочитал здесь , существует тайм-аут от 4 до 8 минут (после того, как SqlConnection.Close()вызывается в коде ), после чего он закрывает соединение с базой данных для источник данных. Похоже, это соответствует сценарию 2, о котором я упоминал выше.

Это наводит меня на мысль, что это связано с SqlConnectionиспользуемым (и базовым подключением базы данных к источнику данных), поскольку в моем случае включен пул соединений, но почему я наблюдаю это поведение и как его исправить?

Мы используем.Net 2.0 Framework, если это имеет значение.

Выше перечислено много мелких деталей, поэтому, пожалуйста, дайте мне знать, если мне нужно что-то уточнить.

Единственный вопрос о переполнении стека с каким-либо сходством — это этот , но он не имел отношения к моей проблеме.

Изменить: Следующий код выполняется в моем тестовом приложении WinForms при запуске:

SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder();

connectionStringBuilder.DataSource = m_DataSource;
connectionStringBuilder.InitialCatalog = m_InitialCatalog;
connectionStringBuilder.UserID = m_UserID;
connectionStringBuilder.Password = m_Password;
connectionStringBuilder.IntegratedSecurity = false;
connectionString = connectionStringBuilder.ConnectionString;

m_DatabaseConnection = new SqlConnection(connectionString);

Затем у меня есть 2 кнопки; один из которых вызывает SPROC 1 , упомянутый выше, а другой вызывает другой SPROC, который не имеет такой же проблемы с замедлением.Следующий код выполняется при нажатии любой кнопки (с той лишь разницей, что имя SPROC):

m_DatabaseConnection.Open();
m_DatabaseCommand = new SqlCommand("GetCompanies", m_DatabaseConnection);
m_DatabaseCommand.Parameters.AddWithValue("@StatusID", StatusID);
m_DatabaseCommand.CommandType = CommandType.StoredProcedure;
m_DatabaseCommand.CommandTimeout = 0;

SqlDataAdapter databaseDataAdapter = new SqlDataAdapter(m_DatabaseCommand);
DataSet databaseDataSet = new DataSet();
databaseDataAdapter.Fill(databaseDataSet);
m_DatabaseConnection.Close();

7
задан Community 23 May 2017 в 10:34
поделиться