我有一个基本上是select *的查询。在开发中,这个表只有30000行,但是在生产中它会大得多。所以我想懒洋洋地使用这个查询。为什么下面的查询不懒惰?我正在使用Postgres 9.5.4.1。
(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发布于 2018-05-29 16:44:47
clojure.java.jdbc支持本机对大型结果集的延迟处理(这里的其他答案早于本机支持)。请参阅这里的社区文档:
sql#处理-结果集-懒惰
特别是,请参阅附加选项?部分,了解您可能需要的特定于数据库的调整。可以在任何打开新连接的函数上指定:auto-commit? false,也可以在任何与查询相关的函数上指定:fetch-size和各种游标控件。有关StackOverflow可能需要什么的详细信息,请参阅下面的PostgreSQL问答:
目前,要获得更多这样的选项,您必须深入clojure.java.jdbc源代码参考文献。我正在继续编写社区文档,以公开所有这些信息。
发布于 2016-09-29 15:59:48
首先,请参阅https://jdbc.postgresql.org/documentation/83/query.html#query-with-cursor。
就这样解决了。
(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] ...)}))其中,:result-set-fn是一个消耗延迟结果集的函数。
with-db-transaction负责将autoCommit设置为false。:fetch-size不是从query传递的,所以你必须自己做一个prepare-statement。
发布于 2016-09-30 00:48:13
你不需要上面的交易和准备好的报表。正是:result-set-fn的使用导致了延迟序列的消耗。您可能打算使用:row-fn代替。
有关详细信息,请看“衣柜烹饪书”。还提供了打印版本,我建议这样做。
jdbc/query函数有几个可选的关键字参数,这些参数控制它如何构造返回的结果集。结果集-fn参数指定一个函数,该函数在返回之前应用于整个结果集(一个惰性序列)。默认参数是doall函数:
(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"}]row -fn参数指定在构造结果时应用于每个结果行的函数。默认参数是identity函数:
(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"})https://stackoverflow.com/questions/39765943
复制相似问题