it-swarm.com.de

Datenbankverbindungen erstellen - Einmal oder für jede Abfrage?

Im Moment erstelle ich eine Datenbankverbindung, wenn meine Webseite zum ersten Mal geladen wird. Ich verarbeite dann die Seite und führe alle Abfragen für diese Verbindung aus. Ist dies der beste Weg, oder sollte ich jedes Mal, wenn ich eine Abfrage ausführe, eine Datenbankverbindung erstellen?

ps Es ist für mich sinnvoller, eine Verbindung herzustellen und zu verwenden, aber ich weiß nicht, ob dies andere Probleme verursachen kann.

Ich verwende C # (ASP.NET) mit MSSQL.

119
webnoob

Wenn Sie eine pro Abfrage/Transaktion erstellen, ist es viel einfacher, das "Schließen" der Verbindungen zu verwalten.

Ich kann verstehen, warum der gesunde Menschenverstand vorschreibt, dass Sie eine öffnen und durchgehend verwenden sollten, aber Sie werden auf Probleme mit unterbrochenen Verbindungen und Multithreading stoßen. Ihr nächster Schritt besteht also darin, einen Pool mit beispielsweise 50 Verbindungen zu öffnen und alle offen zu halten, um sie an verschiedene Prozesse weiterzugeben. Und dann werden Sie herausfinden, dass genau das tut das .NET Framework bereits für Sie .

Wenn Sie eine Verbindung bei Bedarf öffnen und nach Abschluss entsorgen, wird die Verbindung dadurch nicht geschlossen, sondern nur an den Verbindungspool zurückgegeben, um erneut verwendet zu werden.

139
pdr

Es wird empfohlen, eine Verbindung pro Abfrage zu erstellen. Bei der Anzeige von Daten empfiehlt es sich, die Abfrage all die erforderlichen Daten auf einmal einzubringen.

Hintergrundinformationen :

In .NET wird beim Aufrufen von SqlConnection.Open() standardmäßig immer transparent Verbindungspooling verwendet (siehe "Verwenden des Verbindungspoolings mit SQL Server" auf MSDN). Sie können also einfach mit Open() eine neue Verbindung herstellen und Close() aufrufen, wenn Sie fertig sind, und .NET wird das Richtige tun.

Beachten Sie, dass ohne Verbindungspooling eine Verbindung pro Abfrage eine sehr schlechte Idee wäre, da das Erstellen realer Datenbankverbindungen sehr kostspielig sein kann (Authentifizierung, Netzwerk-Overhead usw.) und die Anzahl der gleichzeitig geöffneten Verbindungen normalerweise sehr begrenzt ist.

39
Oded

Entwickler möchten manchmal ihren Code "optimieren", um ihre Verbindungsobjekte wiederzuverwenden. Angesichts des Kontextes dieser Frage, der uns in das .Net-Ökosystem versetzt, ist dies fast immer ein Fehler. (Hinweis: Viele andere Plattformen behandeln dies ebenfalls auf ähnliche Weise.).

ADO.Net verfügt über eine Funktion namens Connection Pooling . Wenn Sie ein neues Verbindungsobjekt erstellen und öffnen, fordern Sie tatsächlich eine Verbindung aus einem Pool an. Wenn Sie eine Verbindung schließen, geben Sie sie an den Pool zurück.

Es ist wichtig, die Objekte zu verstehen, die wir direkt im Code verwenden: SqlConnection, MySqlConnection, OleDbConnection usw. sind alles nur Wrapper um eine echte zugrunde liegende Verbindung, die von ADO.Net verwaltet wird, und das ADO.Net real Verbindungen sind vom Leistungsstandpunkt aus viel "schwerer" und teurer. Es sind diese zugrunde liegenden Objekte, die Probleme wie Authentifizierung, Netzwerkübertragung, Verschlüsselung usw. haben, und diese Dinge überwiegen bei weitem die geringe Speichermenge in dem Objekt, die Sie tatsächlich in Ihrem eigenen Code sehen.

Wenn Sie versuchen, Ihr Verbindungsobjekt wiederzuverwenden, gewinnen Sie Effizienz in der kleinen Sache auf Kosten der viel größeren Sache , weil Sie die Fähigkeit brechen für ADO.Net, um die wichtigen zugrunde liegenden Verbindungen effektiv zu verwalten.

Die Wiederverwendung einer Verbindung über eine Anwendung oder eine http-Anforderung kann Sie auch dazu zwingen, versehentlich etwas zu serialisieren, das andernfalls möglicherweise parallel ausgeführt werden könnte, und zu einem Leistungsengpass werden. Ich habe dies in realen Anwendungen gesehen.

Im Fall des hier gezeigten Webseitenbeispiels, bei dem Sie zumindest die kleine Verbindung nur für die Dauer einer einzelnen http-Anforderung/Antwort beibehalten, können Sie noch effizienter werden, indem Sie bewerten, welche Abfragen Sie in Ihrer Anforderungspipeline ausführen, und versuchen, diese abzurufen Sie beschränken sich auf so wenige separate Anforderungen wie möglich an die Datenbank (Hinweis: Sie können mehr als eine Abfrage in einer einzelnen SQL-Zeichenfolge senden und DataReader.NextResult() verwenden oder verschiedene Tabellen in einer DataSet an überprüfen zwischen ihnen bewegen).

Mit anderen Worten, anstatt daran zu denken, eine Verbindung für eine Anwendung oder eine http-Anfrage gegenüber einer Verbindung pro Abfrage wiederzuverwenden, denken Sie an eine Verbindung für jedes Mal, wenn Sie die Datenbank aufrufen ... für jede Hin- und Rückfahrt. Versuchen Sie dann, die Anzahl der Verbindungen zu minimieren, indem Sie die Anzahl dieser Fahrten minimieren. Auf diese Weise können Sie beide Ziele erreichen.


Aber das ist nur eine Art der Optimierung. Es gibt auch eine Optimierung der Programmiererzeit und eine effektive Wiederverwendung von Code. Entwickler möchten nicht immer wieder denselben Boilerplate-Code schreiben, um ein Verbindungsobjekt zu erhalten, das offen und einsatzbereit ist. Es ist nicht nur langweilig, es ist auch eine Möglichkeit, Fehler in ein Programm einzuführen.

Selbst hier ist es im Allgemeinen immer noch besser, eine Verbindung pro Abfrage (oder Hin- und Rückfahrt) zu haben. Es gibt Muster, mit denen Sie vermeiden können, dass derselbe Boilerplate-Code neu geschrieben wird, während das Ziel einer Verbindung pro Aufruf der Datenbank beibehalten wird. Hier ist ein Beispiel Ich mag, aber es gibt viele andere.

2
Joel Coehoorn