[英]How to use prepared statement efficiently using datastax java driver in Cassandra?
[英]Using Prepared Statement multiple times efficiently
下面是我使用 Prepared Statement 在 Oracle 數據庫中插入multiple records( around 5000-7000)
的代碼。
我目前的做法好嗎? 或者它可以使用一些batch thing
來改進?
pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL);
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.executeUpdate();
pstatement.clearParameters();
}
我正在使用的更新代碼:-
public void runNextCommand() {
Connection db_connection = null;
PreparedStatement pstatement = null;
int batchLimit = 1000;
boolean autoCommit = false;
try {
db_connection = getDBConnection();
autoCommit = db_connection.getAutoCommit();
db_connection.setAutoCommit(false); //Turn off autoCommit
pstatement = db_connection.prepareStatement(LnPConstants.UPSERT_SQL); // create a statement
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : GUID_ID_MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.addBatch();
batchLimit--;
if(batchLimit == 0){
pstatement.executeBatch();
pstatement.clearBatch();
batchLimit = 1000;
}
pstatement.clearParameters();
}
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e);
} finally {
try {
pstatement.executeBatch();
db_connection.commit();
db_connection.setAutoCommit(autoCommit);
} catch (SQLException e1) {
getLogger().log(LogLevel.ERROR, e1.getMessage(), e1.fillInStackTrace());
}
if (pstatement != null) {
try {
pstatement.close();
pstatement = null;
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace());
}
}
if (db_connection!= null) {
try {
db_connection.close();
db_connection = null;
} catch (SQLException e) {
getLogger().log(LogLevel.ERROR, e.getMessage(), e.fillInStackTrace());
}
}
}
}
您可以考慮使用addBatch()
並一次性執行后面的語句。 另外,正如@pst 在您的問題中評論的那樣,請考慮使用trasaction
。
你會做的方式如下:
boolean autoCommit = connection.getAutoCommit();
try{
connection.setAutoCommit(false //Turn off autoCommit
pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL);
int batchLimit = 1000;
try{
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : MAPPING.entrySet()) {
pstatement.setInt(1, entry.getKey());
pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
pstatement.setString(4, entry.getValue().get(LnPConstants.SGUID_ID));
pstatement.setString(5, entry.getValue().get(LnPConstants.UID_ID));
pstatement.setString(6, entry.getValue().get(LnPConstants.ULOC_ID));
pstatement.setString(7, entry.getValue().get(LnPConstants.SLOC_ID));
pstatement.setString(8, entry.getValue().get(LnPConstants.PLOC_ID));
pstatement.setString(9, entry.getValue().get(LnPConstants.ALOC_ID));
pstatement.setString(10, entry.getValue().get(LnPConstants.SITE_ID));
pstatement.addBatch();
batchLimit--;
if(batchLimit == 0){
pstatement.executeBatch();
pstatement.clearBatch();
batchLimit = 1000;
}
pstatement.clearParameters();
}
}finally{
//for the remaining ones
pstatement.executeBatch();
//commit your updates
connection.commit();
}
}finally{
connection.setAutoCommit(autoCommit);
}
這個想法是為批量更新設置一個限制,並且只有在達到特定限制時才執行數據庫更新。 這樣,您將數據庫調用限制為您定義的每個batchLimit
一次。 這樣會更快。
還要注意transaction
,我剛剛展示了如何以及何時commit
。 這可能並不總是正確的commit
點,因為此決定將基於您的要求。 您可能還希望在發生異常時執行rollback
。 因此,由您決定。
查看“使用事務”教程,以更好地了解如何使用transaction
。
你的一段代碼對我來說似乎很好。
只是為了代碼清潔,我將entry.getValue()
放入一個變量中(稱之為value
)。
並且沒有必要調用clearParameters()
。
最后,記住在不再需要准備好的語句時正確處理它( close()
)。
是的,進行批量更新會顯着提高您的性能。 只需谷歌,我的首選答案是來自 Mkyong.com 的答案。 否則,您的代碼看起來不錯。 “clearParameters()”並不是真正需要的,它甚至可能會消耗一些處理器周期。 重要提示:如果啟用了 AutoCommit,請不要忘記之前禁用它,並在更新后啟用它,這再次帶來了巨大的改進。
附言
以上建議也是基於我的經驗。 我剛剛注意到這個問題已經在 Stackoverflow上提出過,答案非常詳細。 有關 PreparedStatements 和批次的更多信息,請參見此處的 Oracle 文檔和此處的事務(自動提交)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.