我会依次解决您的问题。
- executeBatch方法会尝试一次发送所有数据吗?
对于每个JDBC驱动程序,这可能会有所不同,但是我研究的少数驱动程序将遍历每个批处理条目,并每次将参数与准备好的语句句柄一起发送给数据库以执行。也就是说,在上面的示例中,将执行50,000条带有50,000对参数的已准备好的语句,但是这50,000个步骤可以在较低级别的“内部循环”中完成,这是节省时间的地方。颇为夸张的类比,这就像退出“用户模式”进入“内核模式”并在那里运行整个执行循环。您可以为每个批次条目节省进出该较低级别模式的潜水成本。
- 有没有一种方法可以定义批量大小
您已经在这里隐式定义了它,方法是在通过执行批处理之前将50,000个参数集推入
Statement#executeBatch()。批大小为1同样有效。
- 有没有更好的方法来加快批量插入的过程?
考虑在批量插入之前显式打开事务,然后再提交。不要让数据库或JDBC驱动程序在批处理中的每个插入步骤周围施加事务边界。您可以使用
Connection#setAutoCommit(boolean)方法控制JDBC层。首先使连接脱离
自动提交模式
,然后填充批次,启动事务,执行批次,然后通过提交事务
Connection#commit()。
该建议假定您的插入不会与并发编写器竞争,并且假定这些事务边界将为您提供从源表中读取的足够一致的值以用于插入。如果不是这种情况,则主张正确性胜于速度。
- 使用可更新的
ResultSet
还是PreparedStatement
批量执行的更好?
没有什么比与您所选择的JDBC驱动程序进行测试,但我希望latter-
PreparedStatement和
Statement#executeBatch()将在这里胜出。语句句柄可能具有“批处理参数”的关联列表或数组,每个条目都是在
Statement#executeBatch()和和
Statement#addBatch()(或
Statement#clearBatch())调用之间提供的参数集。该列表随每次调用而增加
addBatch(),直到您调用时才会刷新
executeBatch()。因此,该
Statement实例实际上充当了参数缓冲区。为了方便起见,您在交换内存(使用
Statement实例代替您自己的外部参数集缓冲区)。
同样,只要我们不讨论 特定的
JDBC驱动程序,就应该考虑这些答案的一般性和推测性。每个驱动程序的复杂程度各不相同,并且每个驱动程序在追求的优化方面也各不相同。



