繁体   English   中英

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

[英]Fastest way to batch query an ORACLE Database with Java

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

对于每种组合,我需要能够查看数据库并确定是否存在具有相同组合的记录。 如果不存在任何记录,那么它将被添加到数据库中。 如果记录确实存在,那么将使用新信息更新记录。

源和目标是表的主键,也是索引。 所有这些都在ORACLE数据库上。

鉴于我必须这样做一百万次,最佳的解决方案是什么? 我当前的方法需要一个多小时才能处理所有记录。

对于实际插入和更新记录,我使用的是批量查询过程,该过程根本不需要花费很多时间。

看起来花费最多时间的部分是查询数据库中现有记录的数量。

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;

最简单的解决方案是放弃计数,而仅使用MERGE语句。 这使数据库可以确定是在单个SQL事务中插入还是更新。 了解更多。

MERGE的一个缺点是,行数不能区分更新的行和插入的行。 这可能是为节省整体时间付出的便宜价格。 尽管如果真的不能没有单独的统计, Adrian Billington可以为您提供解决方法

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

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

另一种方法是预先将所有现有记录的主键加载到内存中,并从记录列表中排除重复项(考虑到您拥有所需的RAM数量)

还要看看这个那个选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM