在NCHAR / NVARCHAR2上,Oracle defaultNChar = true SLOW

时间:2014-12-10 10:13:25

标签: jdbc oracle11g nvarchar

我正在使用带有一组参数的JDBC Prepared Statement,使用setString(pos,value)。表中的基础列都是NCHAR和NVARCHAR2。我已经设置了Oracle JDBC驱动程序" defaultNChar = true"以便Oracle DB始终将我的参数视为国家语言字符。驱动程序文件是" ojdbc6.jar"。

我的问题:我的参数化查询非常慢," defaultNChar = true" 。但是一旦我设置" defaultNChar = false"查询超快(3秒)。

查询用法如下:

String sql = "INSERT INTO MYTABLE_ERROR(MY_NAME,MY_FLAG,MY_VALUE) "
                        + "SELECT ? AS MY_NAME,"
                        + "? AS MY_FLAG,v.MY_VALUE"
                        + " FROM OTHER_TABLE v"
                        + " JOIN ( SELECT * FROM ... iv ... WHERE iv.MY_NAME = ? ) rule1 "
                        + " ON v.\"MY_NAME\"=rule1.\"MY_NAME\" AND v.\"MY_VALUE\"=rule1.\"MY_VALUE\""
                        + " WHERE rule1.\"MY_NAME\" = ? AND v.\"MY_VALUE\" = ?";

preStatement = conn.prepareStatement (sql);
int count = 1;
for (String p : params)
{
        // SLOW
        //preStatement.setNString (count++, p);
        // SLOW
        //preStatement.setObject (count++, p, Types.NVARCHAR);
        // SLOW
        preStatement.setString (count++, p);
}

我一直在努力找到为什么我准备好的语句针对" Oracle数据库11g版本11.2.0.3.0 - 64位生产"执行的根本原因。使用JDBC驱动程序" Oracle JDBC驱动程序,11.2.0.3.0和#34;,DB速度很慢。我找不到任何线索!

我甚至得到了数据库NLS配置希望找到任何东西,但我不确定这里:

NLS_LANGUAGE    AMERICAN
NLS_TERRITORY   AMERICA
NLS_CURRENCY    $
NLS_ISO_CURRENCY    AMERICA
NLS_NUMERIC_CHARACTERS  .,
NLS_CALENDAR    GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE   AMERICAN
NLS_CHARACTERSET    AL32UTF8
NLS_SORT    BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT    DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT  HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY   $
NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_COMP    BINARY

请帮忙!

谢谢, -G。

更新:在使用" defaultNChar = true"时,看起来查询卡住了。不知何故。我在使用JConsole时看到了这个:

Total blocked: 1  Total waited: 1

Stack trace: 
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(Unknown Source)
java.net.SocketInputStream.read(Unknown Source)
oracle.net.ns.Packet.receive(Packet.java:311)
oracle.net.ns.DataPacket.receive(DataPacket.java:103)
oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:312)
oracle.net.ns.NetInputStream.read(NetInputStream.java:257)
oracle.net.ns.NetInputStream.read(NetInputStream.java:182)
oracle.net.ns.NetInputStream.read(NetInputStream.java:99)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:121)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:77)
oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1173)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:309)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:200)
oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:543)
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:238)
oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1446)
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1757)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4372)
oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4539)
   - locked oracle.jdbc.driver.T4CConnection@7f2315e5
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:5577)
com.mycompany.test.DriverTest.fireStatement(DriverTest.java:253)

1 个答案:

答案 0 :(得分:0)

您可以使用PreparedStatement.setFormOfUse解决性能问题:

但是,如果将defaultNChar设置为true,然后访问CHAR列, 那么数据库将隐式地将所有CHAR数据转换为NCHAR。 这种转换会对性能产生重大影响。为了避免这种情况, 为每个CHAR调用setFormOfUse(4,OraclePreparedStatement.FORM_CHAR) 声明中提到的列。例如:

    PreparedStatement pstmt =
    conn.prepareStatement("insert into TEST values(?,?,?)");
    pstmt.setInt(1, 1); // NUMBER column
    pstmt.setString(2, myUnicodeString1); // NVARCHAR2 column
    pstmt.setString(3, myUnicodeString2); // NCHAR column
    pstmt.setFormOfUse(4, OraclePreparedStatement.FORM_CHAR);
    pstmt.setString(4, myString); // CHAR column
    pstmt.execute();

https://docs.oracle.com/cd/B19306_01/java.102/b14355/global.htm#CHDHHJDB