是否可以通过 JDBC/Java 使用直接路径插入?

Posted

技术标签:

【中文标题】是否可以通过 JDBC/Java 使用直接路径插入?【英文标题】:Is it possible to use direct path insertion with JDBC/Java? 【发布时间】:2013-06-18 19:31:14 【问题描述】:

我们有一个用 C 和 Pro*C 编写的应用程序,它使用主机阵列和批量插入将日志文件中的数据插入到 Oracle 11.2 数据库中。这使用APPENDNOLOGGING 提示来利用直接路径插入并减少生成的重做量。 NOLOGGING 对此很有意义,因为它是一个临时临时表,如果需要,可以从日志文件中恢复数据。

我们正在尝试在 Java 中复制此功能,但无法使用直接路径插入大量记录。 Java/JDBC 可以做到这一点吗?

我尝试和调查的事情是:

JDBC 批处理(标准批处理和Oracle's extensions)。这种方法节省了往返时间,但这可以忽略不计,因为应用程序与数据库位于同一台机器上。它也不使用直接路径。 APPEND_VALUES 提示。这听起来很有希望,但意义不大,因为 JDBC 批处理似乎并未实际执行许多记录的“数组”插入。

据我了解,直接路径插入仅支持the subquery syntax and not the VALUES clause。无法使用,因为要插入的数据在数据库中尚不存在。

我一直找不到任何关于 Java 能够使用 Pro*C 使用的主机数组样式加载的参考。

顺便说一句,我们正在研究外部表加载或 SQL*loader 并赞赏这些工具能够直接加载路径,但这个问题实际上是关于是否可以从 Java 中直接插入路径得到明确的答案。了解 Java API 的局限性不仅对本项目有用,对以后的项目也有用。

所以重申一下这个问题,有没有一种方法可以利用 Java 的直接路径插入?

相关问题:

Oracle direct-load INSERTs through JDBC?

【问题讨论】:

你找到通过jdbc直接插入的方法了吗? 不。看起来不可能。我们最终只使用传统的路径加载并对其进行并行化。我仍然希望有人会过来指出我错过的东西。 我看到 smb 能够测试它,但是在他的情况下它没有用:asanga-pradeep.blogspot.com/2014/10/… @BurhanAli - 也许尝试使用 jdbc oci 驱动程序。它应该是基于 OCI C 的功能之上的 JNI 层。 如果你只能使用子查询语法而不是使用INSERT INTO table_name ( value ) SELECT 'literal' FROM DUAL UNION ALL SELECT 'other' FROM DUAL 【参考方案1】:

我找到this answer:

直接路径插入只能在作为 select * from y 场景的插入 x 中进行。这可以使用jdbc来完成,没问题。这不能通过插入和值来完成。当数据库处于强制记录模式时,这也无法完成。大多数情况下,当备用数据库处于连接状态时,主数据库将处于强制记录模式。

正如 Gary Myers 所提到的,从 11gR2 开始就有 APPEND_VALUES 提示。与“旧”附加提示一样,它只能用于批量插入。

【讨论】:

【参考方案2】:

Oracle 文档清楚地说明了这一点:

    If you are performing an INSERT with the VALUES clause, specify the APPEND_VALUES hint in 
each INSERT statement immediately after the INSERT keyword. Direct-path INSERT with the VALUES
 clause is best used when there are hundreds of thousands or millions of rows to load. The
  typical usage scenario is for array inserts using OCI. Another usage scenario might be inserts in a FORALL statement in PL/SQL

.

所以对您的问题的回答是 APPEND_VALUES 提示。我可以在您的帖子中看到您已经尝试过,但无法弄清楚您遇到了什么问题。

您帖子中的此断言也不正确“据我了解,直接路径插入仅支持子查询语法而不支持 VALUES 子句。” Oracle 文档给出了这个例子:

以下 PL/SQL 代码片段是使用 APPEND_VALUES 提示的示例:

FORALL i IN 1..numrecords
  INSERT /*+ APPEND_VALUES */ INTO orderdata 
  VALUES(ordernum(i), custid(i), orderdate(i),shipmode(i), paymentid(i));
COMMIT;

oracle 文档链接:http://docs.oracle.com/cd/E11882_01/server.112/e25494/tables004.htm#i1009100

示例代码:

dbConnection.setAutoCommit(false);//commit trasaction manually

String insertTableSQL = "INSERT /*+ APPEND_VALUES */ INTO DBUSER"
            + "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
            + "(?,?,?,?)";              
PreparedStatement = dbConnection.prepareStatement(insertTableSQL);

preparedStatement.setInt(1, 101);
preparedStatement.setString(2, "test1");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement.addBatch();

preparedStatement.setInt(1, 102);
preparedStatement.setString(2, "test2");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement.addBatch();
preparedStatement.executeBatch();

dbConnection.commit();

【讨论】:

我已经尝试过了,它不会触发直接路径插入,因为您仍然一次只插入一条记录,而不是一个数组(如 OP 所述,如图所示PL/SQL 示例)。 APPEND_VALUES 有许多限制才能生效,以便触发直接路径加载。 另外——“直接加载 INSERT(串行或并行)只能支持 INSERT 语句的 INSERT ... SELECT 语法,而不支持 INSERT... values 语法”,来自 docs.oracle.com/cd/A58617_01/server.804/a58227/ch_dlins.htm

以上是关于是否可以通过 JDBC/Java 使用直接路径插入?的主要内容,如果未能解决你的问题,请参考以下文章

如何用SQL语句将数据批量插入数据库

用直接路径(direct-path)insert提升性能的两种方法

Typora设置图片插入路径

使用jdbc在mysql数据库中插入5000条记录需要太多时间

JDBC Java 数据库插入语句

纯 JDBC / Java 中的 DAO 教程 [关闭]