使用Java批量查询ORACLE数据库的最快方法

时间:2014-01-31 21:13:40

标签: java sql oracle

在我正在进行的项目中,我获得了一个包含少于100万行的列表。数据将所有可能的起源(000-999)映射到所有可能的目的地(000-999)。

对于每个组合,我需要能够查看数据库并确定是否存在具有相同组合的记录。如果不存在记录,则将其添加到数据库中。如果记录确实存在,则记录将使用新信息进行更新。

原点和目标是表的主键,也是索引。 这都在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;

2 个答案:

答案 0 :(得分:0)

最简单的解决方案是抛弃计数并使用MERGE语句。这允许数据库确定是在单个SQL事务中插入还是更新。 Find out more.

MERGE的一个缺点是rowcount不区分更新的行和插入的行。这可能是为节省的总时间支付的便宜价格。虽然如果你真的离不开单独的计数,Adrian Billington has a workaround for you

答案 1 :(得分:-1)

正如APC所提到的 - 当您需要插入或更新时,MERGE是一个不错的选择。但这可能会更新您不想更新的记录。

第一个问题是唯一标识记录的主键是什么(它是多个字段的组合)?

另一种方法可能是加载所有现有记录&#39;事先将主键存入内存并排除从记录列表中复制(考虑到您拥有所需的RAM量)

另请查看thisthat选项。