2012-04-11 8 views
7

Ausführen des gleichen Stored Procedure von C# .Net-Anwendung über ein Netzwerk wird zunehmend langsamer mit jeder weiteren Ausführung. Es scheint zweimal die Menge der Zeit als die vorherige Ausführung zu nehmen (bis zu einem maximalen Wert; lesen Sie weiter). Die Ausführungszeit wird zunehmend langsamer, bis 1 von 2 Szenarien eintritt. Zu diesem Zeitpunkt ist die erste Ausführung des SPROC wieder "schnell".Ausführungszeit Langsamer mit jeder Wiederholung des gleichen SPROC

  1. Wenn ein SqlConnection geöffnet und bleibt offen bei allen Tests, die SPROC wird zunehmend langsamer, bis jede andere SPROC oder Abfrage ausgeführt wird.
  2. Wenn eine SqlConnection wird geöffnet und geschlossen um jede Ausführung, die SPROC wird zunehmend langsamer, bis mindestens 8 Minuten hat bestanden.

Dies geschieht nur mit ein paar Stored Procedures. Eine ist eine einfache SELECT Abfrage mit 2 JOINs, (SPROC 1) eine andere ist eine massive 1600+ Linie SPROC (SPROC 2).

Die Ausführungszeiten erscheinen nie für SPROC 1 und 67 Sekunden SPROC 2 über genau 60 Sekunden zu gehen. SPROC 1 dauert zunächst weniger als eine Sekunde und SPROC 2 dauert zunächst 7 Sekunden.

Dies tritt auch nur auf, wenn der SPROC mit derselben SqlConnection in der Anwendung ausgeführt wird. Sobald zwei separate Objekte SqlConnection verwendet werden, verhalten sie sich wie oben beschrieben, sind jedoch unabhängig. Die SPROC mehrmals auf SqlConnection1 läuft langsam langsamer, aber das erste Mal das gleiche SPROC auf SqlConnection2 ausgeführt wird, ist es "schnell". Es wird dann auch langsamer, wenn es mehrmals auf SqlConnection2 ausgeführt wird.

Dies geschieht nicht, wenn die Anwendung auf demselben Computer mit SQL Server 2008 R2 (unter Windows Server 2008) ausgeführt wird. Die Ausführungszeit ist immer konsistent.

Das Ausführen der Stored Procedure in Management Studio wird auch nicht mit jeder Ausführung langsamer; es ist immer konsistent.

Das Löschen des Ausführungsplancaches (in SQL Server) hat keine Auswirkung auf das beobachtete Verhalten.

Es hat einige Tage gedauert, dieses Problem, das ursprünglich in einer viel größeren Anwendung beobachtet wurde, einzugrenzen, um eine Test-App zu erstellen, die es einfach testet/reproduziert.

Von dem, was ich here gelesen habe, gibt es eine Zeitüberschreitung von zwischen 4 und 8 Minuten (nach SqlConnection.Close() im Code aufgerufen wird) an diesem Punkt schließt die Datenbankverbindung zur Datenquelle. Dies scheint mit dem oben erwähnten Szenario 2 übereinzustimmen.

Dies führt mich zu glauben, an die (und die zugrunde liegende Datenbank-Verbindung zur Datenquelle) verwendete SqlConnection verwendet ist, da Connection Pooling ist in meinem Fall aktiviert, aber warum bin ich dieses Verhalten zu beobachten, und wie kann ich das beheben es?

Wir verwenden das .Net 2.0 Framework, wenn das einen Unterschied macht.

Es gibt viele feine Details, die oben aufgeführt sind, also lassen Sie mich bitte wissen, wenn ich irgendetwas klären muss.

Die einzige Stack Overflow Frage mit Ähnlichkeiten ist this, aber war nicht mit meinem Problem verbunden.

Edit: Der folgende Code in meinem WinForms Test-App beim Start ausgeführt wird:

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); 

Ich habe dann zwei Tasten; von denen eine ruft SPROC 1 oben erwähnt, und die andere ruft eine andere SPROC, die nicht die gleiche Verlangsamung Problem hat. Der folgende Code wird auf beide Tastenklick ausgeführt (einzigen Unterschied ist der SPROC Name):

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(); 
+1

Dies kann etwas besser auf [dba] (http://dba.stackexchange.com/) gepostet werden. – Oded

+1

Dies muss an Ihrem Code liegen. Da Sie uns Ihren Code jedoch nicht gezeigt haben, können wir Ihnen nicht helfen. –

+0

@JohnSaunders - Ich kann die Abfrage für SPROC 1 wenn gewünscht, aber ich glaube nicht, dass jemand von der Linie SPROC 2 1600+ profitieren wird. – njb

Antwort

3

Hier meine Ideen sind, dieses Problem zu debuggen:

  • Versuchen SqlConnection.ClearAllPools() aufgerufen, nachdem die Entsorgung Verbindung. Wenn dadurch das Problem behoben wird, ist das Problem sicher mit einer bestimmten Verbindung verbunden.
  • Als nächstes schließen Sie die SPROC in einer expliziten Transaktion.
  • Rufen Sie als Nächstes SqlConnection.ClearAllPools() auf, bevor Sie den SPROC aufrufen.
  • Wie viele Daten gibt der SPROC zurück?
  • Geben Sie den C# -Code ein, den Sie verwenden, um die Verbindung zu öffnen, und führen Sie SPROC aus.
  • Erstellen Sie eine eigenständige Konsolenanwendung, die das angezeigte Verhalten reproduziert. Dies wird (wahrscheinlich) beweisen, dass etwas in Ihrer App das Problem ist, weil die Konsolen-App gut läuft.
+0

Ich werde jetzt beginnen, Ihre Vorschläge zu versuchen, danke. SPROC 1 gibt höchstens 10 Datensätze mit 11 Spalten zurück. SPROC 2 gibt 2 Datensätze mit 15 Spalten zurück. – njb

+0

Der Aufruf von ClearAllPools() nach dem Disposed behebt das Problem, genau wie das Aufrufen vor dem Aufruf von SPROC. Das Umschließen des SPROC in einer expliziten Transaktion (in .Net - TransactionScope-Objekt) behebt das Problem ebenfalls. Es "funktioniert", aber was verursacht das Problem wirklich? Dies wird alles in meiner eigenständigen WinForms Test App getestet. – njb

+0

Wenn eine Verbindung zum Pool zurückgegeben wird, wird die Isolationsstufe nicht zurückgesetzt. Dies könnte das Problem sein. Versuchen Sie, die tran zu entfernen, führen Sie jedoch "set transaction isolation level read committed" aus, bevor Sie den Prozess ausführen. Wird das Problem dadurch behoben? – usr

Verwandte Themen