データベースから数百万行を読み取り、テキスト ファイルに書き込もうとしています。
これは、副作用のあるテキスト ファイルへの質問データベース ダンプの続きです。
私の問題は、プログラムが完了するまでログが記録されないことです。遅延処理を行っていないことを示すもう 1 つの指標は、プログラムが終了するまでテキスト ファイルがまったく書き込まれないことです。
IRC のヒントに基づいて、私の問題はコードの領域に関係していて:result-set-fn
、デフォルトになっている可能性が高いようです。doall
clojure.java.jdbc/query
これを関数に置き換えようとしましたfor
が、結果セット全体をメモリに取り込むため、メモリ消費量が多いことがわかりました。
:result-set-fn
のようにすべてを引っ張らないようにするにはどうすればよいdoall
ですか? -main
実行が終了したら すべてをダンプするのではなく、プログラムの実行中にログ ファイルを段階的に書き込むにはどうすればよいですか?
(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))
)