优化oracle jdbc批量插入

abc*_*bet 5 java oracle jdbc

我需要使用JDBC将大量插入(即两位数百万)插入Oracle-DB.为此,我使用类似下面的类,灵感来自使用JDBC进行批量INSERTS高效方法:

public class Inserter {
    private final int batchSize;
    private final Connection con; // with .setAutoCommit(false)
    private final PreparedStatement ps;
    private int currentSize = 0;

    public Inserter(Connection con, PreparedStatement ps, int batchSize) {
        this.con = con;
        this.ps = ps;
        this.batchSize = batchSize;
    }

    public void addInsert(Object[] vals) throws SQLException {
        ps.clearParameters(); // should be redundant, but better safe than sorry
        for (int i = 0; i < val.length; i++) {
            this.ps.setObject(i + 1, vals[i]);
        }
        ps.addBatch();
        currentSize++;

        if (currentSize >= batchSize) {
            ps.executeBatch();
            currentSize = 0;
        }
    }

    public void flush() {/** to flush leftovers */}
}
Run Code Online (Sandbox Code Playgroud)

虽然这种插入方式很好,但速度很慢.JDBC批处理插入性能描述了基本上如何处理MySQL的确切问题,rewriteBatchedStatements但是在Oracle上似乎不存在它在这里没有多大帮助.

为了提高性能,我还尝试将Statement切换为一个大INSERT ALL .../ INSERT APPEND ...语句,根据Oracle 11g - 插入多行的最有效方法,这使得一切都更慢.

因此,我的问题是,如果有任何方法可以优化这些插入,而不仅仅是使用addBatch()executeBatch()?或者Inserter上面的课程中是否存在一些严重,低效的错误?任何帮助将非常感谢.


更有用的信息:

  • 要插入的表被分区,每个分区大约有一到一千万行.

  • 对于这样的表有一个唯一约束, unique(id1, id2, id3, id4)其中的所有列都是类型,NUMBER并且进一步由外键约束绑定到其他表中的主键.


编辑:

根据评论中的建议,我将setObject(index, val)电话转为:

  1. setInt(index, val),setFloat(index, val),...,setNull(index, type)调用其中apprpropriate

  2. setObject(index, val, type)setNull(index, typR)

两个版本都没有显着提高性能.

此外,我尝试将数据插入到临时表中,没有任何约束,这也没有带来更好的性能.

为了进行比较,将数据导出为CSV并使用SQL*Loader将其加载导致显着的性能提升,即对于最慢的表1,每秒~4.5k => ~50k +行.

这让我相信JDBC存在的瓶颈.

1 唉,在我的特定情况下,SQL*Loader的使用不是(期望的)选项.

Ska*_*out -1

你永远不会提交该批次。如果可以在未提交查询的情况下在executeBatch之后添加提交,您将创建较大的回滚段,从而降低数据库速度。还要删除 ps.clearParameters() 因为您总是覆盖所有参数或不覆盖任何参数。最好使用专门版本的 setter 而不是 setObject