我正在使用以下代码
st = connection.createStatement(
ResultSet.CONCUR_READ_ONLY,
ResultSet.FETCH_FORWARD,
ResultSet.TYPE_FORWARD_ONLY
);
st.setFetchSize(1000);
System.out.println("start query ");
rs = st.executeQuery(queryString);
System.out.println("done query");
Run Code Online (Sandbox Code Playgroud)
查询返回大量(800k)行,并且在打印"开始查询"和"完成查询"之间需要很长时间(~2m).当我在查询中手动设置"限制10000"时,"开始"和"完成"之间没有时间.处理结果需要花费时间,所以我想如果它只是从数据库中获取1k行,处理这些行,并且当它用尽行时它可以在后台获得新行,则总体上更快.
结果集.CONCUR_READ_ONLY等我最后猜测的地方; 我错过了什么吗?
(这是一个postgresql 8.3服务器)
我正在尝试从数据库中读取数百万行并写入文本文件.
这是我的问题数据库转储到带有副作用的文本文件的延续
我现在的问题似乎是在程序完成之前不会发生日志记录.我没有懒惰处理的另一个指标是在程序完成之前根本不写入文本文件.
基于一个IRC尖看来我的问题很可能具有做:result-set-fn,缺省值为doall在clojure.java.jdbc/query代码的区域.
我试图用一个for函数替换它,但仍然发现内存消耗很高,因为它将整个结果集拉入内存.
我怎么能有一个:result-set-fn不会把所有东西都拉进来的doall?如何在程序运行时逐步编写日志文件,而不是在-main执行完成后转储所有内容?
(let [
db-spec local-postgres
sql "select * from public.f_5500_sf "
log-report-interval 1000
fetch-size 100
field-delim "\t"
row-delim "\n"
db-connection (doto ( j/get-connection db-spec) (.setAutoCommit false))
statement (j/prepare-statement db-connection sql :fetch-size fetch-size )
joiner (fn [v] (str (join field-delim v ) row-delim ) )
start (System/currentTimeMillis)
rate-calc (fn [r] (float (/ r (/ ( - (System/currentTimeMillis) start) 100))))
row-count …Run Code Online (Sandbox Code Playgroud) 通常,我需要从数据库服务器加载巨大的数据量。有时它有上百万行甚至更多。因此,我尝试延迟下载数据。那就是我想要做的:我想获得一个惰性序列并从服务器中提取部分数据,即,如果行数超过500,我主要希望首先获得该惰性序列的前500个元素,然后通过另一个请求得到我要接收下500个元素,依此类推,直到我从服务器接收到所有数据。
但是我有一个问题。Clojure jdbc实现了整个惰性序列,但是我想部分地从中获取数据。我研究了这个问题,并找到了关于类似问题的良好答案: clojure.java.jdbc惰性查询
我以这个例子为例:
(defn get_data
[arg1 arg2]
(let [full-db-spec (get ...)
sql_query (get ...)
row-n (atom 0)
prepared-statement (-> full-db-spec
(jdbc/get-connection)
(jdbc/prepare-statement sql_query {:fetch-size 3}))]
(jdbc/with-db-transaction [tx full-db-spec]
(jdbc/query full-db-spec [prepared-statement arg1 arg2]
{:fetch-size 3
:row-fn (fn [r] (do (prn "r" @row-n) (swap! row-n inc) r))
:result-set-fn identity}))))
Run Code Online (Sandbox Code Playgroud)
在这里,我想获得一个惰性序列,以进一步从该惰性序列中部分提取数据。但是何时:result-set-fn包含identity或(take 500 ...)代码返回错误:The result set is closed.为什么?但是,当我将:result-set-fn更改为first或doall或last时,它工作正常,但它实现了完整的延迟序列!
我用:
[com.microsoft.sqlserver/mssql-jdbc "6.3.3.jre8-preview"](但是我在postgresql上进行了测试[org.postgresql/postgresql "9.4.1212.jre7"]。结果相同)我们有一张m1包含数百万条记录的表格.我们希望生成一个表格,m2其中包含每个记录的计算结果m1.我们目前运行如下:
(jdbc/with-db-transaction [tx connection]
(jdbc/query tx
[(jdbc/prepare-statement (:connection tx)
"select * from m1"
{:fetch-size 1000})]
{:result-set-fn (process! [tx result-set] ...)}))
Run Code Online (Sandbox Code Playgroud)
这里process!是
(defn process! [tx result-set]
(jdbc/with-db-transaction [tx tx]
(jdbc/insert-multi! tx :m2 [:m2_column]
(mapv (fn [r] [(calculate r)])
result-set))))
Run Code Online (Sandbox Code Playgroud)
该select查询使用游标并懒洋洋地消耗掉.请参阅:clojure.java.jdbc延迟查询.这就是它被包装在外部事务中的原因.
问题:
我试图从一个Postgre数据库移动5,000,000行到另一个.两个连接都在Hikari CP连接池中.
我经历了很多文档和帖子.它给我留下了下面的代码.但它并不真正有用:
(jdbc/with-db-connection [tx {:datasource source-db}]
(jdbc/query tx
[(jdbc/prepare-statement (jdbc/get-connection tx)
answer-sql
{:fetch-size 100000})]
{:result-set-fn (fn [result-set]
(jdbc/insert-multi!
{:datasource target-db}
:migrated_answers
result-set))}))
Run Code Online (Sandbox Code Playgroud)
我尝试了很多不同的形式.jdbc/with-db-transaction或者我能想到的任何其他东西都没有多大帮助.
很多教程和帖子只提到了如何整体处理结果的方式.对于进入RAM的小桌子来说绝对可以,但它看起来很快.但这种情况并非如此.
因此,当我正确使用:fetch-size并且我的RAM没有爆炸(hocus pocus)比传输IS非常慢时,两个连接在DB端的"活动"和"事务中的空闲"状态之间切换.我从没等过这么久才发现任何实际转移的数据!
当我在Talend Open Studio(生成Java代码的ETL工具)中创建这个简单批处理时,它会在5分钟内传输所有数据.并且光标大小"也"设置为100000.我认为Clojure的干净代码应该更快.
我得到的最快结果是使用下面的代码.我认为这是因为:as-array参数.如果我不使用:max-rows参数内存爆炸,因为它没有被懒惰地处理,所以我不能将它用于整个transfet.为什么?我不明白这里的规则.
(jdbc/with-db-transaction [tx {:datasource source-db}]
(jdbc/query tx
[(jdbc/prepare-statement (:connection tx)
answer-sql
{:result-type :forward-only
:concurrency :read-only
:fetch-size 2000
:max-size 250000})]
{:as-arrays? true
:result-set-fn (fn [result-set]
(let [keys (first result-set)
values (rest result-set)]
(jdbc/insert-multi!
{:datasource dct-db}
:dim_answers
keys values)))}))
Run Code Online (Sandbox Code Playgroud)我将非常感谢我明显缺少的任何帮助或信息.