我正在尝试让一个函数将数据库 sql 转储从 select 语句写入文本文件。返回的卷可能非常大,我有兴趣尽快完成此操作。
对于大型结果集,我还需要记录每个 x 间隔写入的总行数以及自上次 x 间隔以来每秒写入的行数。我有一个(map)实际上是在(with-open)期间进行写入,所以我相信记录完成的行的副作用应该发生在那里。(参见代码中的注释)。
我的问题是:
- 我如何在间隔期间写“每秒行数”和“到目前为止的总行数”?
- 在将大型 jdbc 结果集写入文件(或命名管道、批量加载程序等)时,我还有什么要记住的吗?
- (map ) 函数周围的 (doall ) 是否获取所有结果...使其非惰性且可能占用大量内存?
可以选择固定宽度吗?我相信命名管道到批量加载器会更快。权衡将在磁盘 i/o 上代替下游解析的 CPU 利用率。但是,这可能需要对返回的结果集进行自省(使用 .getMetaData?)
(ns metadata.db.table-dump [:use [clojure.pprint] [metadata.db.connections] [metadata.db.metadata] [clojure.string :only (join)] [taoensso.timbre :only (debug info warn error set-config!)] ] [:require [clojure.java.io :as io ] [clojure.java.jdbc :as j ] [clojure.java.jdbc.sql :as sql] ] ) (set-config! [:appenders :spit :enabled?] true) (set-config! [:shared-appender-config :spit-filename] "log.log") (let [ field-delim "\t" row-delim "\n" report-seconds 10 sql "select * from comcast_lineup " joiner (fn [v] (str (join field-delim v ) row-delim ) ) results (rest (j/query local-postgres [sql ] :as-arrays? true :row-fn joiner )) ] (with-open [wrtr (io/writer "test.txt")] (doall (map #(.write wrtr %) ; Somehow in here i want to log with (info ) rows written so ; far, and "rows per second" every 10 seconds. results )) ) (info "Completed write") )