Jdbc Clojure core.async。如何用go块惰性下载里面用open?
这是我上一个问题的继续 我想按部分从数据库下载数据。最初我下载前500行,然后发送请求获取下500行,依此类推,直到我从服务器接收到所有数据 我写了代码:Jdbc Clojure core.async。如何用go块惰性下载里面用open?,jdbc,clojure,lazy-evaluation,core.async,Jdbc,Clojure,Lazy Evaluation,Core.async,这是我上一个问题的继续 我想按部分从数据库下载数据。最初我下载前500行,然后发送请求获取下500行,依此类推,直到我从服务器接收到所有数据 我写了代码: (jdbc/atomic conn (with-open [cursor (jdbc/fetch-lazy conn [sql_query])] (let [lazyseq (jdbc/cursor->lazyseq cursor) counter (atom 1)] (swap! lazyseq_m
(jdbc/atomic conn
(with-open [cursor (jdbc/fetch-lazy conn [sql_query])]
(let [lazyseq (jdbc/cursor->lazyseq cursor)
counter (atom 1)]
(swap! lazyseq_maps assoc :session_id {:get_next? (chan 1) :over_500 (chan 1) :data []})
(>!! (:get_next? (:session_id @lazyseq_maps)) true)
(go
(doseq [row lazyseq]
(swap! counter inc)
(when (<! (:get_next? (:session_id @lazyseq_maps)))
(swap! lazyseq_maps update-in [:session_id :data] conj row)
(if (not= 0 (mod @counter 500))
(>! (:get_next? (:session_id @lazyseq_maps)) true)
(>! (:over_500 (:session_id @lazyseq_maps)) true))))
;
(close! (:get_next? (:session_id @lazyseq_maps)))
(close! (:over_500 (:session_id @lazyseq_maps)))
(.close conn))
(when (<!! (:over_500 (:session_id @lazyseq_maps))) {:message "over 500 rows"
:id :session_id
:data (:data (:session_id @lazyseq_maps))}))))
(jdbc/原子连接
(使用open[cursor(jdbc/fetch-lazy-conn[sql\u-query])]
(让[lazyseq(jdbc/cursor->lazyseq cursor)
计数器(原子1)]
(swap!lazyseq_maps assoc:session_id{:get_next?(chan 1):超过500(chan 1):数据[])
(>!!(:get_next?(:session_id@lazyseq_maps))true)
(去
(doseq[第lazyseq行]
(交换柜台公司)
(何时(!(:get_next?(:session_id@lazyseq_maps))true)
(>!(:超过500(:session_id@lazyseq_maps))真)
;
(关闭!(:get_next?(:session_id@lazyseq_maps)))
(关闭!(:超过500(:session_id@lazyseq_maps)))
(关闭控制室)
(何时)(
我在doseq循环的帮助下获取行。当doseq通过500行时,我停止循环(当),并等待来自外部的信号来获取下一个500行
但这里我有一个问题。当我发送信号时,程序抛出错误“Resultset is closed”(结果集关闭)。也就是说,连接在打开的作用域外部关闭。但我不明白为什么,因为go块放在打开的作用域内部。你能帮我解决这个问题吗?(go…
立即返回,因此,(打开时…)
您可能希望以另一种方式进行:
(转到(打开…)
但是,请注意,此过程可能会保留数据库连接(一种稀缺资源!)很长时间,这可能是不可取的,而且由于go
块的存在,这与使用“轻量级”线程的好处是背道而驰的
- 也许可以为每个批重新打开数据库连接
- 也许您可以将整个结果集流式传输到外部存储(例如AWS S3),并让客户对此进行投票
除非您使用的是内存严重受限的系统,否则我建议您立即将所有行加载到RAM并关闭DB连接。否则,您的完整解决方案可能会非常复杂,难以测试和推理
如果您有数千万行,那么您可以在某些分区中获取它们