Ich versuche, Millionen von Zeilen aus einer Datenbank zu lesen und in eine Textdatei zu schreiben. clojure.java.jdbc/Abfrage große Ergebnismenge träge
Dies ist eine Fortsetzung meiner Frage database dump to text file with side effects
Mein Problem scheint jetzt zu sein, dass die Protokollierung nicht passieren, bis das Programm abgeschlossen ist. Ein weiterer Hinweis darauf, dass ich nicht langsam arbeite, ist, dass die Textdatei erst geschrieben wird, wenn das Programm beendet ist.
Basierend auf einem IRC-Tipp scheint es, dass mein Problem wahrscheinlich mit :result-set-fn
und doall
im Bereich clojure.java.jdbc/query
des Codes zu tun hat.
Ich habe versucht, dies durch eine for
Funktion zu ersetzen, aber immer noch feststellen, dass Speicherverbrauch hoch ist, da es die gesamte Ergebnismenge in den Speicher zieht. Wie kann ich eine :result-set-fn
haben, die nicht alles wie doall
zieht? Wie kann ich die Protokolldatei progressiv schreiben, während das Programm ausgeführt wird, anstatt alles zu dumpen, sobald die Ausführung beendet ist?
(let [
db-spec local-postgres
sql "select * from public.f_5500_sf "
log-report-interval 1000
fetch-size 100
field-delim "\t"
row-delim "\n"
db-connection (doto (j/get-connection db-spec) (.setAutoCommit false))
statement (j/prepare-statement db-connection sql :fetch-size fetch-size)
joiner (fn [v] (str (join field-delim v) row-delim))
start (System/currentTimeMillis)
rate-calc (fn [r] (float (/ r (/ (- (System/currentTimeMillis) start) 100))))
row-count (atom 0)
result-set-fn (fn [rs] (lazy-seq rs))
lazy-results (rest (j/query db-connection [statement] :as-arrays? true :row-fn joiner :result-set-fn result-set-fn))
]; }}}
(.setAutoCommit db-connection false)
(info "Started dbdump session...")
(with-open [^java.io.Writer wrtr (io/writer "output.txt")]
(info "Running query...")
(doseq [row lazy-results]
(.write wrtr row)
))
(info (format "Completed write with %d rows" @row-count))
)
ich die Verbindung hinzugefügt haben, machte das: Ergebnis-Typ vorwärtsgerichteten, hinzugefügt Cursor , machte es: schreibgeschützt, und setze die fetch-size auf 1000 und dann auf 100. Ich habe immer noch keine jvm heap size, wenn ich versuche, größere result sets zu holen. Ich habe meine Frage oben aktualisiert, um den neuen Code einzuschließen ... ich bin ratlos, was an dieser Stelle begierig sein könnte ... – joefromct
@joegrangect, versuche Autocommit zu deaktivieren - '(.setAutoCommit db-connection false) '. Ich habe es dem Beispielcode in meiner Antwort hinzugefügt. Nebenbei, ein Teil der Schwierigkeit besteht darin, dass "setFetchSize" lediglich ein Hinweis auf den Treiber ist ([gemäß den API-Dokumenten] (http://docs.oracle.com/javase/1.5.0/docs/api/java/). sql/Statement.html # setFetchSize (int))), so wie es interpretiert wird, kann zwischen den Treibern variieren. PostgreSQLs [JDBC-Dokumente] (http://jdbc.postgresql.org/documentation/head/query.html) zeigen jedoch an, dass es unterstützt wird. Ich denke, wir müssen nur die richtige Beschwörungsformel finden. – jbm
Um zu verdeutlichen, 'setFetchSize' ist eine Methode' prepare-statement', die intern basierend auf dem ': fetch-size'-Argument aufgerufen wird, nicht etwas Zusätzliches, das Sie in Ihrem Code benötigen. – jbm