[英]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.