Jdbc 数据库转储到文本文件,对“文件”有副作用;“行已完成”;

Jdbc 数据库转储到文本文件,对“文件”有副作用;“行已完成”;,jdbc,clojure,Jdbc,Clojure,我试图让一个函数从select语句将数据库sql转储写入文本文件。返回的卷可能非常大,我有兴趣尽可能快地执行此操作 对于较大的结果集,我还需要记录每个x间隔写入的行总数以及自上次x间隔以来每秒写入的行数。我有一个(map)实际上是在(打开时)进行写操作,所以我相信记录完成的行的副作用应该发生在那里。(参见代码中的注释) 我的问题是: 如何在间隔期间写入“每秒行数”和“到目前为止的总行数” 在将大型jdbc结果集写入文件(或命名管道、大容量加载器等)时,我还想记住什么 (map)函数周围的(doa

我试图让一个函数从select语句将数据库sql转储写入文本文件。返回的卷可能非常大,我有兴趣尽可能快地执行此操作

对于较大的结果集,我还需要记录每个x间隔写入的行总数以及自上次x间隔以来每秒写入的行数。我有一个(map)实际上是在(打开时)进行写操作,所以我相信记录完成的行的副作用应该发生在那里。(参见代码中的注释)

我的问题是:

  • 如何在间隔期间写入“每秒行数”和“到目前为止的总行数”
  • 在将大型jdbc结果集写入文件(或命名管道、大容量加载器等)时,我还想记住什么
  • (map)函数周围的(doall)是否获取所有结果。。。使其非惰性且可能占用大量内存
  • 是否可以选择固定宽度?我相信命名管道到批量装载机的速度会更快。取舍将是磁盘i/o,而不是下游解析的CPU利用率。但是,这可能需要对返回的结果集进行内省(使用.getMetaData?)


  • 你可以从我对你的回答中得到一些帮助

    具体到你的情况

    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级别,您可能需要使用
      setFetchSize
      ,以避免在到达Clojure之前将整个结果集加载到RAM中。看
    • 确保Culjur.JavaJDBC实际上返回了一个懒惰的SEQ(它可能是)?如果没有,考虑
    • doall
      确实会强制整个东西都在RAM中;请改为尝试
      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)))))))