8

multiple records( around 5000-7000)以下は、プリペアドステートメントを使用してOracleデータベースに挿入するために使用しているコードです。

私の現在のやり方は良いですか?またはそれはいくつかを使用してさらに改善することができますか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());
            }
        }
    }
}
4

3 に答える 3

9

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このようにして、データベース呼び出しを、定義したものごとに1回に制限します。このようにすると、より高速になります。

また、についても注意してください。transactionこれまで、どのように、いつ行うかを示しましたcommitcommitこの決定は要件に基づいているため、これが常に正しいポイントであるとは限りません。rollback例外の場合に実行することもできます。ですから、決めるのはあなた次第です。

の使用方法をよりよく理解するには、 「トランザクションの使用」チュートリアルを参照してくださいtransaction

于 2012-08-23T21:58:33.370 に答える
1

あなたのコードは私には良さそうです。

コードをきれいにするためentry.getValue()に、変数に入れます(これを呼び出しますvalue)。
そして、を呼び出す必要はありませんclearParameters()

最後に、必要がなくなったときに、準備されたステートメントを正しく破棄することを忘れないでください(close())。

于 2012-08-23T21:58:40.973 に答える
1

はい、バッチ更新を行うとパフォーマンスが大幅に向上します。ちょうどそれのためにグーグル、私の好ましい答えはMkyong.comからのこれです。それ以外の場合、コードは問題ないように見えます。「clearParameters()」は実際には必要ありません。プロセッササイクルを消費することもあります。重要:AutoCommitが有効になっている場合は、前に無効にし、更新後に有効にすることを忘れないでください。これにより、大幅な改善がもたらされます。

PS

上記の推奨事項も私の経験に基づいています。この質問はすでにStackoverflowで行われており、その答えは非常に詳細です。PreparedStatementsとバッチの詳細については、ここのOracleドキュメント、およびここのトランザクション(AutoCommit)についての詳細を参照してください

于 2012-08-23T22:09:35.087 に答える