[英]Java For loop with batch SQL
我有個問題。 現在我正在使用 JOOQ 使用以下代碼在我的數據庫中插入大約 100.000 條記錄:
try (Connection conn = DriverManager.getConnection(SqlConn.getURL(), SqlConn.getUSERNAME(), SqlConn.getPASSWORD())) {
DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
for (String key : trendlines.keySet()) {
for (Trendline trendline : trendlines.get(key)) {
String sql = createTrendlineQuery(trendline);
create.fetch(sql);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
使用 function createTrendlineQuery()
:
private String createTrendlineQuery(Trendline trendline) {
return "INSERT INTO Trendline (openTime, market, coin, period, metric, number, slope, interceptY, percentage, formula, data) VALUES (" +
trendline.getOpenTime() + ", '" +
trendline.getMarket() + "', '" +
trendline.getCoin() + "', '" +
trendline.getPeriod() + "', '" +
trendline.getFormula() + "') " +
"ON DUPLICATE KEY UPDATE " +
"openTime = " + trendline.getOpenTime() + ", " +
"market = '" + trendline.getMarket()+ "', " +
"coin = '" + trendline.getCoin() + "', " +
"period = '" + trendline.getPeriod() + "', " +
"formula = '" + trendline.getFormula() + "';";
}
但這給我的互聯網/數據庫帶來了很大的負擔,所以我發現你可以為大數據進行批量插入。 我在 JOOQ 中找到了關於批量插入的以下頁面: https://www.jooq.org/doc/3.14/manual/sql-execution/batch-execution/ 。 現在我認為這是我需要的,但我有一個問題。 該示例在我的情況下如下所示:
try (Connection conn = DriverManager.getConnection(SqlConn.getURL(), SqlConn.getUSERNAME(), SqlConn.getPASSWORD())) {
DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
create.batch(create.insertInto(DSL.table("Trendline"), DSL.field("openTime"), DSL.field("market"), DSL.field("coin") ).values((Integer) null, null, null))
.bind( trendline.getOpenTime() , trendline.getMarket() , trendline.getCoin() )
.bind( trendline.getOpenTime() , trendline.getMarket() , trendline.getCoin() )
.bind( trendline.getOpenTime() , trendline.getMarket() , trendline.getCoin() )
.bind( trendline.getOpenTime() , trendline.getMarket() , trendline.getCoin() )
.execute();
}
catch (Exception e) {
e.printStackTrace();
}
除了我需要在create.batch()
之間放置 2 個for-loops
以編程方式創建插入。 如何插入for loops
,我是否使用了正確的方式插入來減少 Internet 流量和數據庫壓力?
BatchedConnection
作為快速修復將現有 jOOQ 代碼(或任何基於 JDBC 的代碼)轉換為批處理 JDBC 交互的最簡單解決方案是使用 jOOQ 的BatchedConnection
:
create.batched((Connection c) -> {
// Now work with this Connection c, instead of your own Connection and all the statements
// will be buffered and batched, e.g.
DSL.using(c).insertInto(...).values(...).execute();
});
您只需將BatchBindStep
分配給循環中的局部變量即可:
BatchBindStep step = create.batch(query);
for (...)
step = step.bind(...);
step.execute();
使用導入 API 。 假設您正在使用代碼生成器並且您有通常的 static 導入
import static org.jooq.impl.DSL.*;
import static com.example.generated.Tables.*;
寫這個:
create.loadInto(TRENDLINE)
.onDuplicateKeyUpdate()
.loadArrays(trendlines
.values()
.stream()
.map(t -> new Object[] {
t.getOpenTime(),
t.getMarket(),
t.getCoin(),
t.getPeriod(),
t.getFormula()
/* And the other fields which you partially omitted */
})
.toArray(Object[][]::new)
)
.fields(
TRENDLINE.OPENTIME,
TRENDLINE.MARKET,
TRENDLINE.COIN,
TRENDLINE.PERIOD,
TRENDLINE.FORMULA
/* And the other fields which you partially omitted */
)
.execute();
另請參閱以下部分:
這可能是有趣的。 如果輸入Object[][]
變得太大,您可以手動分塊您的輸入trendlines.values()
集合。 如果按鍵排序你的 map 真的很重要(我不應該從你的問題中看出),然后寫這個:
trendlines
.keySet()
.stream()
.flatMap(k -> trendlines.get(k).stream())
.map(t -> new Object[] { ... })
...
create.fetch(sql)
,而實際上您的語句是具有更新計數的查詢,因此在這種情況下,您可能想改用create.execute(sql)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.