Verwenden der adaptiven Pufferung

Die adaptive Pufferung wurde erstmals in Microsoft SQL Server 2005 JDBC Driver, Version 1.2, unterstützt. Damit können alle Arten von Daten mit großen Werten ohne den Aufwand für Servercursor abgerufen werden. In Anwendungen kann das Feature der adaptiven Pufferung mit allen Versionen von SQL Server verwendet werden, die vom Treiber unterstützt werden.

Wenn Microsoft SQL Server JDBC Driver 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 SQL Server JDBC Driver 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 erzeugt ein sehr großes 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 Versionen 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 große SQLServerResultSet -Spalten oder SQLServerCallableStatement -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 als Datenstrom mithilfe der Methoden getAsciiStream, getBinaryStream, oder getCharacterStream 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 JDBC Driver, Version 2.0, ist das Standardverhalten des Treibers "adaptive". Dies bedeutet, um das Verhalten der adaptiven Pufferung zu verwenden, muss das Verhalten der adaptiven Pufferung in der Anwendung nicht explizit angefordert werden. In Version 1.2 lautete der Puffermodus jedoch standardmäßig "full", 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. Diese frühere Verwendungsweise wird in den Codebeispielen in Beispiel zum Lesen umfangreicher Daten und Beispiel zum Lesen umfangreicher Daten mit gespeicherten Prozeduren veranschaulicht.

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. Beispielcode finden Sie im 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, minimiert die adaptive Pufferung die Anwendungsspeicherauslastung beim Verarbeiten der Ergebnisse. Beim Verwenden der adaptiven Pufferung:

  • Die in der SQLServerResultSet-Klasse und der SQLServerCallableStatement-Klasse definierten get<Type>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<Type>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<Type>Stream-Methoden abgerufenen Werte nur einmal abgerufen werden. Wenn Sie versuchen, eine get<Type>-Methode für die gleiche Spalte oder den gleichen Parameter aufzurufen, nachdem die get<Type>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."

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. Ab Version 1.2 von Microsoft SQL Server 2005 JDBC Driver ermöglicht es das Feature für die adaptive Pufferung Anwendungen, sehr große, schreibgeschützte Vorwärtsresultsets ohne Verwendung eines Servercursors zu verarbeiten. Beachten Sie, dass das Festlegen von selectMethod=cursor sich auf alle schreibgeschützten Resultset mit Vorwärtscursor auswirken, 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 Serverweite mehr Ressourcen verwendet als bei einer selectMethod, die auf einen anderen Wert als cursor festgelegt ist.

  • Lesen Sie große Text- oder Binärwerte als Datenströme mithilfe der Methoden getAsciiStream, getBinaryStream, oder getCharacterStream anstelle der getBlob-Methode oder der getClob-Methode. Ab Version 1.2 stellt die SQLServerCallableStatement-Klasse neue get<Type>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<Type>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<Type>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.

  • In bestimmten Fällen wie den folgenden bietet die Verwendung von selectMethod=cursor gegenüber responseBuffering=adaptive Vorteile:

    • Wenn die Anwendung ein schreibgeschütztes Resultset mit Vorwärtscursor langsam verarbeitet, z. B. beim Lesen jeder Zeile nach einer Benutzereingabe, wird die Ressourcenverwendung durch selectMethod=cursor anstelle von responseBuffering=adaptive 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 adaptive-Parameter aufrufen. Da das Resultset nicht scrollfähig ist, verwirft der Treiber einen großen Spaltenwert, auf den die Anwendung mit einer der get<Type>Stream-Methoden zugreift, wie bei schreibgeschützten Resultsets mit Vorwärtscursor, sobald er von der Anwendung gelesen wurde.

Siehe auch

Andere Ressourcen

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