当前位置: 首页 > 知识库问答 >
问题:

优化oracle jdbc批插入

贝财
2023-03-14

我需要使用JDBC在Oracle数据库中进行大量插入,即两位数百万。为此,我使用了类似于以下类的东西,灵感来自使用JDBC进行批处理插入的高效方法:

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 */}
}

虽然这种插入方式很好,但速度非常慢。JDBC batch insert performance描述了MySQL基本上可以解决这个问题,因为rewriteBatchedStatements在Oracle上似乎不存在,但在这里没有太大帮助。

为了提高性能,我还尝试将语句切换为一个大的INSERT ALL /插入附加 语句,根据Oracle11g,这是插入多行的最有效的方法,这使一切变得更加缓慢。

因此,我的问题是,除了简单地使用addBatch()executeBatch()之外,还有什么方法可以优化这些插入?或者在上面的插入器类中是否存在一些严重的、低效的错误?任何帮助都将不胜感激。

更有用的信息:

>

表上有一个唯一的约束,看起来像这样的unique(id1、id2、id3、id4),其中所有列的类型都是NUMBER,并通过外键约束进一步绑定到其他表中的主键。

编辑:

根据评论中的建议,我将setObject(index, val)调用切换为:

>

  • setInt(index,val)setFloat(index,val)setNull(索引,类型)在适当的位置调用

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

    两个版本都没有显著提高性能。

    此外,我还尝试在没有任何约束的情况下将数据插入临时表,这也没有带来更好的性能。

    相比之下,将数据导出到CSV并使用SQL*Loader加载它会显着提高性能,即~4.5k=

    这让我相信,瓶颈在于JDBC。

    1唉,在我的特殊情况下,使用SQL*Loader不是一个(理想的)选项


  • 共有1个答案

    丌官瀚
    2023-03-14

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

     类似资料:
    • 问题内容: 我在将不同的缓冲区大小插入到本地SQLite DB中时发现,当缓冲区大小为10,000时,插入10,000,000行数据需要花费近8分钟的时间。换句话说,它需要1,000次写入来存储所有内容。 8分钟存储10,000,000个似乎太长了(或者是?) 可以优化以下任何一项以提高速度吗?请注意,插入的数据是字符的随机集合。 创建表格后,通过 是否可以进一步优化上述任何一项? 问题答案: 我

    • 问题内容: 我需要通过REST API的Batch端点将大量节点及其之间的关系插入到Neo4j中,大约每秒5k记录(仍在增加)。 这将是24x7连续插入。每条记录可能只需要创建一个节点,而其他记录可能需要两个节点并创建一个关系。 是否可以通过更改程序或修改Neo4j的设置来提高插入件的性能? 到目前为止,我的进度: 1.我已经使用Neo4j进行了一段时间的测试,但无法获得所需的性能 测试服务器盒:

    • 问题内容: 我有一个脚本,它通过自定义ORM生成数以万计的插入Postgres数据库中。可以想象,它非常慢。这用于开发目的,以便创建伪数据。我可以在Postgres级别上进行简单的优化以使其更快吗?它是唯一按顺序运行的脚本,不需要线程安全。 也许我可以关闭所有锁定,安全检查,触发器等?只是寻找一种快速而肮脏的解决方案,可以大大加快这一过程。 谢谢。 问题答案: 如果您在生产环境中不需要这种功能,建

    • 问题内容: 我试图切换一些硬编码的查询以使用参数化输入,但是遇到一个问题:如何格式化参数化批量插入的输入? 当前,代码如下所示: 一个可能的解决方案(从如何将数组插入到一个带有PHP和PDO的单个MySQL Prepared语句中 修改而来)似乎是: 有没有更好的方法来完成带有参数化查询的批量插入? 问题答案: 好吧,您有三个选择。 一次构建-执行多次。基本上,您只需为一行准备一次插入,然后循环执

    • 我有一个用于将实时数据移动到测试环境中的事务数据置乱的过程。该表包含大约一亿行,分布在50个分区中。每月添加一个新分区。随着音量的增加,过程的执行速度比以前慢。 我正在考虑在我的代码中引入某种程度的并行化。这是一个新领域,我想知道是否有任何最佳实践。也许使用dbms_parallel_execute将更新拆分为块? 任何关于如何优化我的代码的建议都非常感谢! 编辑,我的解决方案基于以下反馈:重写部

    • 订单、叫车凭证、申请单、报销单等统一入口,审核查看更简单。 【新增】申请单支持在PC端进行查看 【优化】将订单、叫车凭证、申请单、报销单等的查询入口统一 【优化】订单支持按角色的管理范围进行展示 【优化】将报销单的审批、查询拆分,此处专注于当前用户的审批功能