我有一个返回大量行的SQL查询。我想将查询结果保存到磁盘上的csv文件中。但是,因为有很多行,所以在sql查询聚合所有行之前我的内存耗尽。
看起来像这样,在查询部分失败:
(-> query format-transformer csv-writer)
答案 0 :(得分:4)
我在#clojure irc频道的帮助下想出来了。你需要两个库:
(ns myproj.example
(:require [[clojure.java.jdbc :as sql]
[clojure.data.csv :as csv]]))
诀窍是在返回时处理每一行,然后丢弃它。 java jdbc库具有查询功能,该功能使用:row-fn
和:result-set-fn
选项提供此功能。
(defn sql->csv [title]
(with-open [w (clojure.java.io/writer (str title ".csv") :append true)]
(sql/query ds (second query)
:row-fn (fn [row]
(csv/write-csv w [(mapv str (vals row))]))
:result-set-fn dorun)))
有趣的部分是:row-fn
和:result-set-fn
。
每次从查询返回一行时,都会调度:row-fn
。每行都是{:column1 "data" :column2 "data2"}
形式的地图。我们将map更改为write-csv可以使用的内容(嵌套向量):[(mapv str (:vals row)])
。然后write-csv将它附加到你给它的文件中。
:result-set-fn
对于不吹你的堆来说至关重要。通过将其设置为dorun
,您可以告诉它在处理时丢弃头部。
这个特定的实现不提供列标题,这是留给读者的一个练习(我的公共论坛上发帖太尴尬了)。