Clojure - 加速大文件处理

use*_*183 6 clojure large-files

我需要读取大文件(~1GB),处理它并保存到db.我的解决方案如下:

data.txt中

格式: [id],[title]\n

1,Foo
2,Bar
...
Run Code Online (Sandbox Code Playgroud)

(ns test.core
  (:require [clojure.java.io :as io]
            [clojure.string :refer [split]]))

(defn parse-line
  [line]
  (let [values (split line #",")]
    (zipmap [:id :title] values)))

(defn run
  []
  (with-open [reader (io/reader "~/data.txt")]
    (insert-batch (map parse-line (line-seq reader)))))

; insert-batch just save vector of records into database
Run Code Online (Sandbox Code Playgroud)

但是这段代码效果不好,因为它首先解析所有行,然后将它们发送到数据库中.

我认为理想的解决方案是read line -> parse line -> collect 1000 parsed lines -> batch insert them into database -> repeat until there is no lines.不幸的是,我不知道如何实现这一点.

bsv*_*gen 12

一个建议:

  • 使用line-seq获得一系列懒惰的行,

  • 使用map来解析每一行,

(到目前为止,这与你正在做的事情相符)

  • 使用partition-all将已解析行的懒惰序列分区为批次,然后

  • 使用带有doseq的 insert-batch 将每个批次写入数据库.

一个例子:

(->> (line-seq reader)
     (map parse-line)
     (partition-all 1000)
     (#(doseq [batch %] 
       (insert-batch batch))))
Run Code Online (Sandbox Code Playgroud)