2016-09-29 3 views
2

기본적으로 select * 인 쿼리가 있습니다. 개발시이 테이블은 단지 30000 행이지만, 생산에서는 훨씬 더 커집니다. 그래서이 쿼리를 늦게 사용하고 싶습니다. 왜 아래의 쿼리가 게으르지 않은가? Postgres 9.5.4.1을 사용하고 있습니다.clojure.java.jdbc 지연 쿼리

(do 
    (def pg-uri {:connection-uri "jdbc:postgresql://localhost/..."}) 
    (def row (atom 0)) 
    (take 10 (clojure.java.jdbc/query 
      pg-uri 
      ["select * from mytable"] 
      {:fetch-size 10 
      :auto-commit false 
      :row-fn (fn [r] (swap! row inc))})) 
    @row) ;;=> 300000 
+0

어쩌면이 나이 S.O. : 기본 인수는 식별 기능입니다 질의 응답은 확실하지 않을 수 있습니다 : http://stackoverflow.com/questions/19728538/clojure-java-jdbc-query-large-resultset-lazily – Josh

답변

2

먼저, https://jdbc.postgresql.org/documentation/83/query.html#query-with-cursor을 참조하십시오.

이렇게 처리했습니다. :result-set-fn

(jdbc/with-db-transaction [tx connection] 
    (jdbc/query tx 
    [(jdbc/prepare-statement (:connection tx) 
           "select * from mytable" 
           {:fetch-size 10})] 
    {:result-set-fn (fn [result-set] ...)})) 

는 지연 결과 집합을 소모하는 기능이다.

with-db-transaction은 을 false으로 설정합니다. :fetch-sizequery에서 전달되지 않으므로 prepare-statement을 직접 만들어야합니다.

0

위의 거래 및 준비된 명세서는 필요하지 않습니다. 게으른 시퀀스가 ​​소모되는 것은 :result-set-fn의 사용입니다. 대신 :row-fn을 사용해야 할 수도 있습니다.

자세한 내용은 please see The Clojure Cookbook. 인쇄 버전을 사용하는 것이 좋습니다.

jdbc/query 함수에는 이 반환 된 결과 집합을 구성하는 방법을 제어하는 ​​몇 가지 선택적 키워드 매개 변수가 있습니다. : result-set-fn 매개 변수는 반환되기 전에 전체 결과 집합 (지연 시퀀스)에 적용되는 함수를 지정합니다.

(defn hi-lo [rs] [(first rs) (last rs)]) 

;; Find the highest- and lowest-cost fruits 
(jdbc/query db-spec 
      ["select * from fruit order by cost desc"] 
      :result-set-fn hi-lo) 
;; -> [{:grade nil, :unit nil, :cost 77, :appearance nil, :name "Kumquat"} 
;;  {:grade 1.4, :unit nil, :cost 10, :appearance "rotten", :name "Tomato"}] 

: 행 fn을 매개 변수는 결과가 구축 될 때마다 결과 행에인가하는 기능을 지정하는 기본 인자 DOALL 함수이다.

(defn add-tax [row] (assoc row :tax (* 0.08 (row :cost)))) 

(jdbc/query db-spec 
      ["select name,cost from fruit where cost = 12"] 
      :row-fn add-tax) 
;; -> ({:tax 0.96, :cost 12, :name "Plum"} {:tax 0.96, :cost 12, :name "Fig"}) 
+1

불행히도 이것은 Postgres에서 작동하지 않습니다. 내 대답의 링크를 참조하십시오. autoCommit을 false로 설정하고 fetchSize를 설정하여 커서로 페칭을 수행해야합니다. 그렇지 않으면 전체 결과 세트가 여전히 메모리에 저장됩니다. Postgres 로그를 켜서 확인하십시오 : LOG : S_1/C_2에서 가져 오기를 실행하십시오 : select * from ... 여기서 '가져 오기'라는 단어는 커서를 사용하여보아야 할 내용입니다. 큰 테이블에서 '모두 선택'을 선택하고 제한된 쿼리 대 시간을 기록하십시오. 제한된 쿼리가 훨씬 빠르다는 것을 알 수 있지만 페칭은 중요하지 않습니다. –

+1

당신은 제한된 쿼리가 훨씬 빠르다는 것을 알게 될 것입니다. 그러나 커서를 사용하면 예를 들어 첫 번째 요소 만 실현한다면 => 문제가되지 않습니다. –

+1

아마도 JDBC/Postgres 쪽이 아니라 Clojure 쪽에서 만 게으른 것일 것입니다 ... 나는 그렇게까지 실험하지 않았습니다. clojure.java.jdbc의 관리자가 자주 있기 때문에이 질문을 clojure Google 그룹에 보내시기 바랍니다. –