我需要使用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不是一个(理想的)选项
你永远不会把这批货交出来。如果可以在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端进行查看 【优化】将订单、叫车凭证、申请单、报销单等的查询入口统一 【优化】订单支持按角色的管理范围进行展示 【优化】将报销单的审批、查询拆分,此处专注于当前用户的审批功能