Große Liste, die von einer SimpleJdbcTemplate-Abfrage zurückgegeben wurde

8

Hier ist mein Problem: Irgendwann in meinem Java-Programm bekomme ich eine (sehr) große Liste von Ereignissen aus einer Datenbank mit der SimpleJdbcTemplate-Klasse von Spring.

%Vor%

Das Problem ist, dass die Liste so etwas wie 600.000 Ereignisse enthalten kann ... Daher viel Speicher verwenden (und auch Zeit brauchen, um verarbeitet zu werden).

Allerdings muss ich nicht wirklich alle Events auf einmal abrufen. Eigentlich möchte ich in der Lage sein, über die Liste zu iterieren, nur ein paar Ereignisse zu lesen (verknüpft mit einer bestimmten KEY_ID - die SQL-Abfrage myQuery ist nach KEY_ID geordnet), zu verarbeiten und schließlich wieder zu iterieren, damit der Garbage Collector los wird die vorherigen und bereits verarbeiteten Ereignisse, so dass ich nie eine bestimmte Menge an Speicher überschreiten.

Gibt es eine gute Möglichkeit, dies mit der Spring-Bibliothek (oder einer anderen Bibliothek) zu tun?

Prost, Vakimshaar.

    
Jean Logeart 07.07.2011, 17:30
quelle

4 Antworten

2

Wenn ich es richtig verstehe, möchten Sie über die Ergebnismenge iterieren, sind aber nicht daran interessiert, die vollständige Liste der Ergebnisse zu erstellen.

Verwenden Sie einfach die Abfrage-Methode mit einem ResultSetExtractor als Argument. Das ResultSetExtractor kann Ihren Mapper verwenden, um die aktuelle Zeile in ein Event umzuwandeln. Fügen Sie jedes Ereignis in eine Liste ein, bis Sie eine andere KEY_ID oder das Ende der Ergebnismenge erreichen. Fahren Sie dann mit der Liste der Ereignisse fort und löschen Sie die Liste.

    
JB Nizet 07.07.2011, 17:47
quelle
5

Ich denke, ein Teil Ihres Problems besteht darin, dass Ihre Abfrage auf einmal ausgeführt wird und Sie das Ergebnis in einem großen Haufen zusammenfassen, der die Speicher- und Netzwerkbandbreite beeinträchtigt. Zusätzlich zu einer Möglichkeit, die Ergebnismenge zu durchlaufen, benötigen Sie eine Möglichkeit, die Ergebnisse aus der Datenbank ein Stück nach der anderen zurückzuholen. Werfen Sie einen Blick auf diese Antwort zu Lazy-Loading Resultsets . Es sieht so aus, als könnten Sie die Abrufgröße in Kombination mit einem ResultSetExtractor festlegen und möglicherweise das gewünschte Verhalten erhalten (abhängig von der Datenbank).

    
Nathan Hughes 07.07.2011 18:45
quelle
3

Sie sollten Ihre SQL-Abfrage so konstruieren, dass nur eine begrenzte Menge von Elementen zurückgegeben wird, die mit einer bestimmten Nummer beginnen. Es ist datenbankspezifische Operation (in Oracle und MySql werden Sie rownum in irgendeiner Form manipulieren). Dann wiederholst du die anruferhöhende Startnummer, bis alle Elemente bearbeitet sind.

Oracle-Beispiel

%Vor%     
Alex Gitelman 07.07.2011 17:34
quelle
1

Vielleicht könnte der folgende Code für Sie nützlich sein?

%Vor%

Hier ist PagingQueryContext:

%Vor%

Es fügt eins zur Abrufgröße hinzu, so dass Sie sehen können, ob es mehr Ergebnisse gibt. Abhängig davon, wie der von Ihnen verwendete JDBC-Treiber implementiert rs.last() implementiert, möchten Sie diesen Aufruf möglicherweise nicht in ResultSetExtractor verwenden und verzichten auf totalRows . Einige Treiber laden möglicherweise alle Daten, wenn last() aufgerufen wird.

    
laz 07.07.2011 19:48
quelle

Tags und Links