2015-04-22 13 views
5

Potrzebuję przeczytać duży plik (~ 1 GB), przetworzyć go i zapisać w db. Moje rozwiązanie wygląda tak:Clojure - Przyspiesz przetwarzanie dużych plików

dane.txt

format: [id],[title]\n

1,Foo 
2,Bar 
... 

kod

(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 

ale ten kod nie działa dobrze, ponieważ po raz pierwszy przeanalizuj wszystkie wiersze, a następnie wyślij je do bazy danych.

Myślę, że idealnym rozwiązaniem będzie read line -> parse line -> collect 1000 parsed lines -> batch insert them into database -> repeat until there is no lines. Niestety, nie mam pojęcia, jak to wdrożyć.

Odpowiedz

11

Jedna sugestia:

  • Zastosowanie line-seq uzyskać leniwy przebieg linii

  • wykorzystanie map do analizowania każdego wiersza,

(do tej pory ten pasuje co ty robimy)

  • użycie partition-all aby podzielić swój leniwy sekwencji analizowanych linii w partii, a następnie

  • użycie insert-partii z doseq napisać każdą partię do bazy danych.

i przykład:

(->> (line-seq reader) 
    (map parse-line) 
    (partition-all 1000) 
    (#(doseq [batch %] 
     (insert-batch batch)))) 
+0

Działa świetnie! Dziękuję Ci bardzo. Widzę, że mam problem ze zrozumieniem leniwych sekwencji. Czy znasz jakieś dobre źródła, które mogą mi pomóc lepiej to zrozumieć? – user1518183

+2

[The Joy of Clojure] (http://www.manning.com/fogus2/) jest świetny. – bsvingen

Powiązane problemy