【发布时间】:2014-02-24 17:49:53
【问题描述】:
在我正在进行的一个项目中,我得到了一个包含不到 100 万行的列表。数据将所有可能的起点 (000-999) 映射到所有可能的目的地 (000-999)。
对于每个组合,我需要能够查看数据库并确定是否存在具有相同组合的记录。如果不存在记录,则将其添加到数据库中。如果记录确实存在,则将使用新信息更新记录。
origin 和destination 是表的主键,也是索引。 这一切都在 ORACLE 数据库上。
鉴于我必须这样做 100 万次,最好的解决方案是什么? 我目前的方法需要一个多小时来处理所有记录。
为了实际插入和更新记录,我使用了一个不需要太多时间的批量查询过程。
似乎花费最多时间的部分是查询数据库以获取现有记录的计数。
public String batchUpdateModes(List records, String user) throws TransactionException {
String message = "";
ArrayList updateList = new ArrayList();
ArrayList insertList = new ArrayList();
Connection conn = null;
try {
conn = getDao().getConnection();
} catch (SQLException e1) {
e1.printStackTrace();
}
for (int i = 0; i < records.size(); i++) {
BatchFileCommand record = (BatchFileCommand)records.get(i);
String origin = record.getOrigZip().trim();
String dest = record.getDestZip().trim();
String pri = record.getPriMode().trim();
String fcm = record.getFcmMode().trim();
String per = record.getPerMode().trim();
String pkg = record.getPkgMode().trim();
String std = record.getStdMode().trim();
String effDate = record.getEffDate();
String discDate = "";
TransModeObj obj = new TransModeObj(origin, dest, pri, fcm, per, pkg, std, effDate, discDate);
obj.setUserId(user);
try {
Statement stmt = null;
String findExisting = "select count(*) from trans_mode where orig_zip = " + origin + " " +
"and dest_zip = " + dest;
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(findExisting);
int count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
if (count > 0) {
updateList.add(obj);
}
else {
insertList.add(obj);
}
rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
message = e.getMessage();
}
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
boolean success = false;
recordCount[0] = updateList.size();
recordCount[1] = insertList.size();
success = insertTransModes(insertList);
System.out.println("Inserts Complete");
success = updateTransModes(updateList);
System.out.println("Updates Complete");
if (success) {
message = "success";
}
else {
message = "The changes or additions submitted could not be completed.";
}
return message;
【问题讨论】:
-
只是和建议,如果您的数据完全格式化,那么您可以简单地使用SQL loader。
-
带有
MERGE的变体很好,但是如果您从外部源加载大量数据,有很多方法可以提供良好的性能。请查看来自this answer 的链接,尤其是带有SQL*Loader 的变体。