我正试图将5,000,000行从一个Postgre DB移到另一数据库。两个连接都在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))}))
我已经尝试了很多不同的形式。jdbc/with-db-transaction
或其他我能想到的没有太大帮助。
许多教程和帖子仅提及如何整体处理结果。用小表进入RAM绝对可以,但是看起来很快。但这种情况并非如此。
因此,当我正确使用:fetch-size
并且我的RAM不会爆炸时,传输就非常慢,因为在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)))}))
我将不胜感激任何帮助或信息,我将不胜感激。
该解决方案最适合我,而且似乎比Taylor的解决方案更快。但是非常感谢您的帮助。
在事务完成之前,它不会提交。我必须遇到任何问题,看看是否不需要拉皮条,但我现在很高兴。我试图用替换第一个事务,with-db-connection
但是它使记录直接加载到RAM中。
(defn data->transfer2 [sql table]
(jdbc/with-db-transaction [read-tx {:datasource dag-db}]
(jdbc/with-db-transaction [tx {:datasource dct-db}]
(jdbc/query read-tx
[(jdbc/prepare-statement (:connection read-tx)
answer-sql
{:result-type :forward-only
:concurrency :read-only
:fetch-size 100000})]
{:as-arrays? true
:result-set-fn (fn [result-set]
(let [keys (first result-set)
values (rest result-set)]
(doseq [btch (partition-all 100000 values)]
(jdbc/insert-multi! tx
:dim_answers
keys
btch))))})))
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句