gpt4 book ai didi

jdbc - clojure.java.jdbc/延迟查询大结果集

转载 作者:行者123 更新时间:2023-12-02 05:30:08 25 4
gpt4 key购买 nike

我正在尝试从数据库读取数百万行并写入文本文件。

这是我的问题 database dump to text file with side effects 的延续

我现在的问题似乎是在程序完成之前不会发生日志记录。我没有延迟处理的另一个指标是,在程序完成之前根本不会写入文本文件。

根据 IRC 提示,我的问题可能与 :result-set-fn 有关,并在 clojure.java 中默认为 doall .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))
)

最佳答案

我通过将 [org.clojure/java.jdbc "0.3.0-beta1"] 放入我的项目中,对 clojure.java.jdbc 进行了最新修复。 clj 依赖项列表。这个增强/纠正了 :as-arrays?描述了 clojure.java.jdbc/query 的 true 功能 here .

我认为这有所帮助,但是我仍然可以将 :result-set-fn 覆盖为 vec

通过将所有行逻辑塞入 :row-fn 中解决了核心问题。最初的 OutOfMemory 问题与迭代 j/query 结果集有关,而不是定义特定的 :row-fn

新的(工作)代码如下:

(defn -main []
(let [; {{{
db-spec local-postgres
source-sql "select * from public.f_5500 "
log-report-interval 1000
fetch-size 1000
row-count (atom 0)
field-delim "\u0001" ; unlikely to be in source feed,
; although i should still check in
; replace-newline below (for when "\t"
; is used especially)
row-delim "\n" ; unless fixed-width, target doesn't
; support non-printable chars for recDelim like
db-connection (doto ( j/get-connection db-spec) (.setAutoCommit false))
statement (j/prepare-statement db-connection source-sql :fetch-size fetch-size :concurrency :read-only)
start (System/currentTimeMillis)
rate-calc (fn [r] (float (/ r (/ ( - (System/currentTimeMillis) start) 100))))
replace-newline (fn [s] (if (string? s) (clojure.string/replace s #"\n" " ") s))
row-fn (fn [v]
(swap! row-count inc)
(when (zero? (mod @row-count log-report-interval))
(info (format "wrote %d rows" @row-count))
(info (format "\trows/s %.2f" (rate-calc @row-count)))
(info (format "\tPercent Mem used %s " (memory-percent-used))))
(str (join field-delim (doall (map #(replace-newline %) v))) row-delim ))
]; }}}
(info "Started database table dump session...")
(with-open [^java.io.Writer wrtr (io/writer "./sql/output.txt")]
(j/query db-connection [statement] :as-arrays? true :row-fn
#(.write wrtr (row-fn %))))
(info (format "\t\t\tCompleted with %d rows" @row-count))
(info (format "\t\t\tCompleted in %s seconds" (float (/ (- (System/currentTimeMillis) start) 1000))))
(info (format "\t\t\tAverage rows/s %.2f" (rate-calc @row-count)))
nil)
)

我尝试过的其他事情(取得了有限的成功)涉及音色记录和关闭标准输出;我想知道使用 REPL 是否可以在显示回我的编辑器(vim 壁炉)之前缓存结果,并且我不确定这是否占用了大量内存。

此外,我还使用 (.freeMemory (java.lang.Runtime/getRuntime)) 添加了围绕内存空闲的日志记录部分。我对 VisualVM 不太熟悉,也不太清楚我的问题出在哪里。

我对现在的工作方式很满意,感谢大家的帮助。

关于jdbc - clojure.java.jdbc/延迟查询大结果集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19728538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com