我正在做我認爲是一個相當直接的任務:使用sqlkorma庫(http://sqlkorma.com)運行一個sql查詢(超過約65K行數據),併爲每一行轉換它某種方式,然後寫入CSV文件。我並不真的認爲65K行的容量非常大,因爲我有8GB的筆記本電腦,但我也認爲一個sql結果集會被延遲取出,所以整個事情永遠不會同時存在內存中。所以,我真的很驚訝,當我結束了與該堆棧跟蹤:clojure sqlkorma庫:內存不足錯誤
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at clojure.lang.PersistentHashMap$BitmapIndexedNode.assoc(PersistentHashMap.java:777)
at clojure.lang.PersistentHashMap.createNode(PersistentHashMap.java:1101)
at clojure.lang.PersistentHashMap.access$600(PersistentHashMap.java:28)
at clojure.lang.PersistentHashMap$BitmapIndexedNode.assoc(PersistentHashMap.java:749)
at clojure.lang.PersistentHashMap$TransientHashMap.doAssoc(PersistentHashMap.java:269)
at clojure.lang.ATransientMap.assoc(ATransientMap.java:64)
at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:56)
at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:100)
at clojure.lang.PersistentArrayMap.createHT(PersistentArrayMap.java:61)
at clojure.lang.PersistentArrayMap.assoc(PersistentArrayMap.java:201)
at clojure.lang.PersistentArrayMap.assoc(PersistentArrayMap.java:29)
at clojure.lang.RT.assoc(RT.java:702)
at clojure.core$assoc.invoke(core.clj:187)
at clojure.core$zipmap.invoke(core.clj:2715)
at clojure.java.jdbc$resultset_seq$thisfn__204.invoke(jdbc.clj:243)
at clojure.java.jdbc$resultset_seq$thisfn__204$fn__205.invoke(jdbc.clj:243)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.PersistentVector.create(PersistentVector.java:51)
at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
at clojure.core$vec.invoke(core.clj:354)
at korma.db$exec_sql$fn__343.invoke(db.clj:203)
at clojure.java.jdbc$with_query_results_STAR_.invoke(jdbc.clj:669)
at korma.db$exec_sql.invoke(db.clj:202)
at korma.db$do_query$fn__351.invoke(db.clj:225)
at clojure.java.jdbc$with_connection_STAR_.invoke(jdbc.clj:309)
at korma.db$do_query.invoke(db.clj:224)
at korma.core$exec.invoke(core.clj:474)
at db$query_db.invoke(db.clj:23)
at main$_main.doInvoke(main.clj:32)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
據我可以從棧來講,它並沒有查詢代碼之外使它(這意味着它沒有達到我的轉變/寫入CSV代碼)。如果它很重要,我的SQL是相當簡單的,基本上SELECT * FROM my_table WHERE SOME_ID IS NOT NULL AND ROWNUM < 65000 ORDER BY some_id ASC
。這是oracle(解釋上面的rownum),但我不認爲這很重要。
編輯:
代碼示例:
(defmacro query-and-print [q] `(do (dry-run ~q) ~q))
(defn query-db []
(query-and-print
(select my_table
(where (and (not= :MY_ID "BAD DATA")
(not= :MY_ID nil)
(raw (str "rownum < " rows))))
(order :MY_ID :asc))))
; args contains rows 65000, and configure-app sets up the jdbc
; connection string, and sets a var with rows value
(defn -main [& args]
(when (configure-app args)
(let [results (query-db)
dedup (dedup-with-merge results)]
(println "Result size: " (count results))
(println "Dedup size: " (count dedup))
(to-csv "target/out.csv" (transform-data dedup)))))
你可以編輯你的OP並添加一些源代碼嗎?同時建議將錯誤塊修剪一下。 – octopusgrabbus 2013-05-02 15:45:35
完成。不知道要從錯誤塊中刪除什麼:它顯示我的代碼沒有超過'(query-db)'調用,它也顯示了在'clojure.java.jdbc'內OOM正在發生的位置。作爲一個便箋,我開始研究'clojure.java.jdbc'代碼,並且它並不像它那樣懶惰(這對我來說很瘋狂)。 – Kevin 2013-05-02 16:03:01
當我添加'(println「結果類型:」(類型結果))'我得到'結果類型:clojure.lang.PersistentVector',我想這回答我的問題。 – Kevin 2013-05-02 16:28:03