簡體   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