Jdbc 数据库转储到文本文件,对“文件”有副作用;“行已完成”;
我试图让一个函数从select语句将数据库sql转储写入文本文件。返回的卷可能非常大,我有兴趣尽可能快地执行此操作 对于较大的结果集,我还需要记录每个x间隔写入的行总数以及自上次x间隔以来每秒写入的行数。我有一个(map)实际上是在(打开时)进行写操作,所以我相信记录完成的行的副作用应该发生在那里。(参见代码中的注释) 我的问题是:Jdbc 数据库转储到文本文件,对“文件”有副作用;“行已完成”;,jdbc,clojure,Jdbc,Clojure,我试图让一个函数从select语句将数据库sql转储写入文本文件。返回的卷可能非常大,我有兴趣尽可能快地执行此操作 对于较大的结果集,我还需要记录每个x间隔写入的行总数以及自上次x间隔以来每秒写入的行数。我有一个(map)实际上是在(打开时)进行写操作,所以我相信记录完成的行的副作用应该发生在那里。(参见代码中的注释) 我的问题是: 如何在间隔期间写入“每秒行数”和“到目前为止的总行数” 在将大型jdbc结果集写入文件(或命名管道、大容量加载器等)时,我还想记住什么 (map)函数周围的(doa
你可以从我对你的回答中得到一些帮助 具体到你的情况 1) 可以将索引作为匿名函数的第二个参数添加到映射中,然后在映射的函数中查看索引以查看正在写入的行。可以用来更新原子
user> (def stats (atom {}))
#'user/stats
user> (let [start-time (. (java.util.Date.) getTime)]
(dorun (map (fn [line index]
(println line) ; write to log file here
(reset! stats [{:lines index
:start start-time
:end (. (java.util.Date.) getTime)}]))
["line1" "line2" "line3"]
(rest (range)))))
line1
line2
line3
nil
user> @stats
[{:lines 3, :start 1383183600216, :end 1383183600217}]
user>
然后每隔几秒钟就可以打印/记录stats
的内容,以更新UI
3) 您肯定希望使用dorun
而不是doall
,因为您怀疑这会在足够大的数据集上耗尽内存dorun
会在写入结果时删除这些结果,这样如果您想等待足够长的时间,就可以在无限大的数据上运行它。两个常规提示:
- 在JDBC级别,您可能需要使用
,以避免在到达Clojure之前将整个结果集加载到RAM中。看setFetchSize
- 确保Culjur.JavaJDBC实际上返回了一个懒惰的SEQ(它可能是)?如果没有,考虑
确实会强制整个东西都在RAM中;请改为尝试doall
doseq
- 考虑使用一个
来记录在运行过程中写入的行数;您可以使用它来写入到目前为止的行,等等atom
(let [ .. your stuff ..
start (System/currentTimeMillis)
row-count (atom 0)]
(with-open [^java.io.Writer wrtr (io/writer "test.txt")]
(doseq [row results]
(.write wrtr row)
(swap! row-count inc)
(when (zero? (mod @row-count 10000))
(println (format "written %d rows" @row-count))
(println (format "rows/s %.2f" (rate-calc-here)))))))
你可以在这里使用而不是
map
。当我进入进度条时,这会很有帮助。。。目前,我只是将一个比率/浮点值输出到一个日志文件中。谢谢
(let [ .. your stuff ..
start (System/currentTimeMillis)
row-count (atom 0)]
(with-open [^java.io.Writer wrtr (io/writer "test.txt")]
(doseq [row results]
(.write wrtr row)
(swap! row-count inc)
(when (zero? (mod @row-count 10000))
(println (format "written %d rows" @row-count))
(println (format "rows/s %.2f" (rate-calc-here)))))))