Verwenden der adaptiven Pufferung

JDBC-Treiber herunterladen

Mit der adaptiven Pufferung können Daten mit großen Werten ohne den Aufwand von Servercursorn abgerufen werden. In Anwendungen kann die Funktion der adaptiven Pufferung mit allen Versionen von SQL Server verwendet werden, die vom Treiber unterstützt werden.

Wenn Microsoft JDBC-Treiber für SQL Server eine Abfrage ausführt, ruft der Treiber normalerweise alle Ergebnisse vom Server in einen Anwendungsspeicher ab. Obwohl bei diesem Ansatz die Ressourcenauslastung für SQL Server reduziert wird, kann ein OutOfMemoryError in der JDBC-Anwendung für die Abfragen ausgelöst werden, bei denen sehr große Ergebnisse zurückgegeben werden.

Damit Anwendungen sehr große Ergebnisse behandeln können, stellt Microsoft JDBC-Treiber für SQL Server die adaptive Pufferung bereit. Mithilfe der adaptiven Pufferung ruft der Treiber Ergebnisse der Anweisungsausführung erst dann von SQL Server ab, wenn sie in der Anwendung benötigt werden, statt alle Ergebnisse auf einmal abzurufen. Der Treiber verwirft außerdem die Ergebnisse, sobald die Anwendung nicht mehr auf sie zugreifen kann. Im Folgenden werden einige Szenarien beschrieben, in denen die Verwendung der adaptiven Pufferung sinnvoll sein kann:

  • Die Abfrage liefert ein sehr umfangreiches Resultset: Die Anwendung kann eine SELECT-Anweisung ausführen, die mehr Zeilen zurückgibt, als im Speicher der Anwendung gespeichert werden können. In vorherigen Releases musste die Anwendung einen Servercursor verwenden, um einen OutOfMemoryError zu vermeiden. Die adaptive Pufferung stellt die Möglichkeit bereit, ein beliebig großes Resultset mit Vorwärtscursor und schreibgeschützt zu übergeben, ohne dass ein Servercursor erforderlich ist.

  • Die Abfrage erzeugt sehr umfangreicheSQLServerResultSet-Spalten oderSQLServerCallableStatement-OUT-Parameterwerte: Die Anwendung kann einen Wert (Spalte oder OUT-Parameter) abrufen, der zu groß ist, um vollständig im Anwendungsspeicher gespeichert zu werden. Durch die adaptive Pufferung kann die Clientanwendung solche Werte mithilfe der Methoden getAsciiStream, getBinaryStream oder getCharacterStream als Datenstrom abrufen. Die Anwendung ruft den Wert beim Lesen des Datenstroms von SQL Server ab.

Hinweis

Mit adaptiver Pufferung puffert der JDBC-Treiber nur die benötigte Datenmenge. Der Treiber stellt keine öffentliche Methode zum Steuern oder Beschränken der Puffergröße bereit.

Festlegen der adaptiven Pufferung

Ab Version 2.0 des JDBC-Treibers ist das Standardverhalten des Treibers adaptiv. Dies bedeutet, um das Verhalten der adaptiven Pufferung zu verwenden, muss das Verhalten der adaptiven Pufferung in der Anwendung nicht explizit angefordert werden. In Release 1.2 lautete der Puffermodus jedoch standardmäßig vollständig, und die Anwendung musste den Modus für die adaptive Pufferung explizit anfordern.

Es gibt drei Möglichkeiten, mit denen eine Anwendung die Verwendung der adaptiven Pufferung für die Anweisungsausführung anfordern kann:

Bei Verwendung von JDBC Driver, Version 1.2, mussten Anwendungen das Anweisungsobjekt in SQLServerStatement umwandeln, um die setResponseBuffering-Methode zu verwenden. Die Codebeispiele in den Artikeln Beispiel zum Lesen umfangreicher Daten und Beispiel zum Lesen umfangreicher Daten mit gespeicherten Prozeduren veranschaulichen diese alte Verwendung.

Mit Version 2.0 des JDBC-Treibers können Anwendungen jedoch die isWrapperFor-Methode und die unwrap-Methode verwenden, um auf die herstellerspezifischen Funktionen zuzugreifen, ohne Vermutungen über die Klassenhierarchie der Implementierung anstellen zu müssen. Einen Beispielcode finden Sie in dem Thema Beispiel zum Aktualisieren umfangreicher Daten.

Abrufen umfangreicher Daten mit adaptiver Pufferung

Wenn große Werte einmal mithilfe der get<Typ>Stream-Methoden gelesen werden und auf die ResultSet-Spalten und die CallableStatement-OUT-Parameter in der Reihenfolge zugegriffen wird, in der sie von SQL Server zurückgegeben werden, wird die Auslastung des Anwendungsspeichers bei der Verarbeitung der Ergebnisse durch die adaptive Pufferung minimiert. Beim Verwenden der adaptiven Pufferung:

  • Die in der SQLServerResultSet-Klasse und der SQLServerCallableStatement-Klasse definierten get<Typ>Stream-Methoden geben schreibgeschützte Datenströme zurück, die zurückgesetzt werden können, wenn sie von der Anwendung gekennzeichnet werden. Wenn in der Anwendung reset für den Datenstrom ausgeführt werden soll, muss zunächst die mark-Methode für diesen Datenstrom aufgerufen werden.

  • Die in der SQLServerClob-Klasse und der SQLServerBlob-Klasse definierten get<Typ>Stream-Methoden geben Datenströme zurück, die immer wieder an der Anfangsposition des Datenstroms positioniert werden können, ohne die mark-Methode aufzurufen.

Wenn die Anwendung adaptive Pufferung verwendet, können die von den get<Typ>Stream-Methoden abgerufenen Werte nur einmal abgerufen werden. Wenn Sie versuchen, eine get<Typ>-Methode für die gleiche Spalte oder den gleichen Parameter aufzurufen, nachdem die get<Typ>Stream-Methode des gleichen Objekts aufgerufen wurde, wird eine Ausnahme mit der folgenden Meldung ausgelöst: „Auf die Daten wurde zugegriffen; sie sind für diese Spalte oder diesen Parameter nicht verfügbar.“

Hinweis

Beim Abrufen von ResultSet.close() während der Verarbeitung eines Resultsets muss der Microsoft JDBC-Treiber für SQL Server alle verbleibenden Pakete lesen und verwerfen. Dies kann erhebliche Zeit in Anspruch nehmen, wenn die Abfrage ein großes Dataset zurückgegeben hat, insbesondere dann, wenn die Netzwerkverbindung langsam ist.

Richtlinien für die Verwendung der adaptiven Pufferung

Entwickler sollten sich an diese wichtigen Richtlinien halten, um die Speicherauslastung durch die Anwendung zu minimieren:

  • Vermeiden Sie die Verwendung der Verbindungszeichenfolgeneigenschaft selectMethod=cursor, damit die Anwendung ein sehr großes Resultset verarbeiten kann. Die adaptive Pufferung ermöglicht Anwendungen, sehr große, schreibgeschützte Vorwärtsresultsets ohne die Verwendung eines Servercursors zu verarbeiten. Beachten Sie, dass das Festlegen von selectMethod=cursor sich auf alle schreibgeschützten Resultsets mit Vorwärtscursor auswirkt, die über diese Verbindung generiert werden. Das heißt, wenn die Anwendung wiederholt kleine Resultsets mit wenigen Zeilen verarbeitet, werden zum Erstellen, Lesen und Schließen eines Servercursors für jedes Resultset sowohl auf Clientseite als auch auf Serverseite mehr Ressourcen verwendet als bei der selectMethod, die auf einen anderen Wert als cursor festgelegt ist.

  • Lesen Sie große Text- oder Binärwerte als Datenströme, indem Sie die Methoden getAsciiStream, getBinaryStream oder getCharacterStream anstelle der getBlob- oder getClob-Methode verwenden. Ab Release 1.2 stellt die SQLServerCallableStatement-Klasse neue get<Typ>Stream-Methoden hierfür bereit.

  • Stellen Sie sicher, dass Spalten mit potenziell großen Werten in der Liste der Spalten in einer SELECT-Anweisung am Ende platziert werden und dass die get<Typ>Stream-Methoden von SQLServerResultSet verwendet werden, um in der Reihenfolge auf die Spalten zuzugreifen, in der sie ausgewählt werden.

  • Stellen Sie sicher, dass OUT-Parameter mit potenziell großen Werten in der Liste der Parameter im SQL zum Erstellen von SQLServerCallableStatement zuletzt deklariert werden. Stellen Sie außerdem sicher, dass die get<Typ>Stream-Methoden von SQLServerCallableStatement verwendet werden, um auf die OUT-Parameter in der Reihenfolge zuzugreifen, in der sie deklariert wurden.

  • Vermeiden Sie, gleichzeitig mehrere Anweisungen über die gleiche Verbindung auszuführen. Das Ausführen einer weiteren Anweisung vor dem Verarbeiten der Ergebnisse der vorhergehenden Anweisung kann dazu führen, dass nicht verarbeitete Ergebnisse im Anwendungsspeicher gepuffert werden.

  • Es gibt einige Fälle, in denen die Verwendung von selectMethod=cursor anstelle von responseBuffering=adaptive vorteilhafter wäre, z. B.:

    • Wenn die Anwendung ein schreibgeschütztes Resultset mit Vorwärtscursor langsam verarbeitet, z. B. beim Lesen jeder Zeile nach einer Benutzereingabe, wird durch Nutzung von selectMethod=cursor anstelle von responseBuffering=adaptive die Ressourcenverwendung durch SQL Server möglicherweise verringert.

    • Wenn die Anwendung zwei oder mehr schreibgeschützte Resultsets mit Vorwärtscursor gleichzeitig für die gleiche Verbindung verarbeitet, lässt sich der vom Treiber bei der Verarbeitung dieser Resultsets benötigte Speicher durch selectMethod=cursor anstelle von responseBuffering=adaptive möglicherweise verringern.

    In beiden Fällen müssen Sie den zusätzlichen Aufwand des Erstellens, Lesens und Schließens der Servercursor berücksichtigen.

Darüber hinaus enthält die folgende Liste einige Empfehlungen für scrollfähige Resultsets und aktualisierbare Resultsets mit Vorwärtscursor:

  • Bei scrollfähigen Resultsets liest der Treiber beim Abrufen eines Zeilenblocks immer die von der getFetchSize-Methode des SQLServerResultSet-Objekts angegebene Anzahl von Zeilen in den Speicher ein, auch bei aktivierter adaptiver Pufferung. Wenn das Scrolling einen OutOfMemoryError verursacht, können Sie die Anzahl der abgerufenen Zeilen verringern, indem Sie die setFetchSize-Methode des SQLServerResultSet-Objekts aufrufen, um die Abrufgröße auf eine kleinere Zeilenanzahl festzulegen und ggf. sogar auf eine Zeile verringern. Führt dies immer noch zu einem OutOfMemoryError, vermeiden Sie das Einschließen sehr großer Spalten in scrollfähigen Resultsets.

  • Bei aktualisierbaren Resultsets mit Vorwärtscursor liest der Treiber beim Abrufen eines Zeilenblocks normalerweise die von der getFetchSize-Methode des SQLServerResultSet-Objekts angegebene Anzahl von Zeilen in den Speicher ein, auch wenn die adaptive Pufferung für die Verbindung aktiviert ist. Wenn das Aufrufen der next-Methode des SQLServerResultSet-Objekts einen OutOfMemoryError verursacht, können Sie die Anzahl der abgerufenen Zeilen verringern, indem Sie die setFetchSize-Methode des SQLServerResultSet-Objekts aufrufen, um die Abrufgröße auf eine kleinere Zeilenanzahl festzulegen und ggf. sogar auf eine Zeile verringern. Sie können auch erzwingen, dass der Treiber keine Zeilen puffert, indem Sie vor dem Ausführen der Anweisung die setResponseBuffering-Methode des SQLServerStatement-Objekts mit dem Parameter adaptiv aufrufen. Da das Resultset nicht scrollfähig ist, verwirft der Treiber einen großen Spaltenwert, auf den die Anwendung mit einer der get<Typ>Stream-Methoden zugreift, wie bei schreibgeschützten Resultsets mit Vorwärtscursor, sobald er von der Anwendung gelesen wurde.

Siehe auch

Verbessern von Leistung und Zuverlässigkeit mit dem JDBC-Treiber