Csv 在clojure中将大文件写入磁盘
我有一个返回大量行的sql查询。我想将查询结果保存到磁盘上的csv文件中。但是,因为有太多的行,所以在sql查询聚合所有行之前,我的内存已经用完了 如下所示,在查询部分失败:Csv 在clojure中将大文件写入磁盘,csv,clojure,Csv,Clojure,我有一个返回大量行的sql查询。我想将查询结果保存到磁盘上的csv文件中。但是,因为有太多的行,所以在sql查询聚合所有行之前,我的内存已经用完了 如下所示,在查询部分失败: (-> query format-transformer csv-writer) 我在clojure irc频道的帮助下找到了答案。您将需要两个库: (ns myproj.example (:require [[clojure.java.jdbc :as sql] [clojure.d
(-> query format-transformer csv-writer)
我在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)))
有趣的部分是:行fn
和:结果集fn
每次从查询返回一行时,都会调度:行fn
。每一行都是一个映射,格式为{:column1“data”:column2“data2”}
。我们将映射更改为csv可以使用的东西(嵌套向量):[(mapv str(:vals row)])
。然后write csv将其附加到给定的文件中
:结果集fn
对于不破坏堆至关重要。通过将其设置为dorun
,您可以告诉它在处理头部时丢弃头部
这个特定的实现没有提供列标题,这是留给读者的一个练习(我的太令人尴尬了,无法在公共论坛上发布)。我假设您的
:row fn
现在可以打开和关闭每一行的文件。更糟糕的是,它必须扫描到文件末尾的每一行。我还没有对它进行测试,但我认为如果在sql/query
之外使用open调用,这可能会更有效。我还认为,根据最新的研究,您实际上想要设置:结果集fn
,而不是:行集fn
。我猜的默认doall
:结果集fn
的作用相同,或者您使用的是旧版本。@schaueho:说得好,谢谢。我已经测试了这些更改,使用open在中运行速度更快。我试着将write csv
函数放入:result set fn
,但结果返回的nils与行数一样多。