oracle 在Java中通过JDBC查询很慢,但在其他系统中不会(TOAD)

jhkqcmku  于 2023-11-17  发布在  Oracle
关注(0)|答案(4)|浏览(139)

你好,我有一个查询到Oracle系统,其中涉及一个视图,该视图通过将TO_NUMBER()应用于表的主键来连接其他表。
如果我使用TOAD进行查询,查询速度非常快(1秒800字节)。如果我使用JDBC在Java程序中使用String literal(不是参数化查询)进行相同的查询,时间也很好。
但是如果我通过PreparedStatement使用参数化查询,查询需要1分钟来获取相同的寄存器。我知道使用常量值比使用参数产生不同的执行计划.但是如果我在视图的连接中删除TO_NUMBER函数,参数化查询也很快。

  • 参数/ TO_NUMBER()联合是否阻止使用连接表的PK索引?
  • 有没有解决这个问题的方法(我需要查询的参数和TO_NUMBER函数)?

P.D.为我糟糕的英语道歉

rqenqsqc

rqenqsqc1#

在没有额外信息的情况下,我们只能假设一个索引没有被使用,而to_number()函数被应用于该列。如this SO question所示,类型转换可以阻止优化器使用索引。
一般而言:

  • 当你向一个列添加一个函数时(即:to_number(id)),优化器将无法使用该列的常规索引,
  • 如果可能的话,应该使用raw列。对于重复:而不是WHERE trunc(col) = DATE '2009-08-27',应该使用:WHERE col >= DATE '2009-08-27' AND col < DATE '2009-08-28',而不是用途:
  • 如果您确实必须将函数应用于列,则可以使用基于函数索引
suzh9iv8

suzh9iv82#

检查参数中传递的Java变量的数据类型是否与Oracle数据类型兼容。当通过与Oracle日期列进行比较的绑定变量传递Java TIMESTAMP时,我看到过类似的症状-文字字符串查询OK,PL/SQL中的测试用例(日期)绑定OK,Java代码w/ mismatch not OK。
[编辑]我认为你已经提供了一些额外的信息,因为最初的帖子。要了解在不同环境(Java和Toad)中查询的形式(绑定和字面量)略有不同的情况,最好的方法是在执行期间启用跟踪,并比较结果跟踪文件中的执行路径。这需要您能够访问数据库主机以检索文件。

  • 在Toad中,打开一个交互式SQL窗口(我不使用Toad,但我相信您会理解我的意思),并发出SQL命令“alter session set sql_trace=true”
  • 运行查询-最好在查询中添加注解,例如“/* Toad with literals */”
  • 对于Java测试,构建一个测试用例,发出“alter session...”语句,然后运行查询。同样,向查询添加注解以标识它来自Java测试。
  • 不要担心关闭跟踪-这将在会话断开连接时发生,并且在某些情况下,首选停止跟踪的断开连接方法。
  • 通过“select value from v$parameter where name like 'user_dump_dest'”找出跟踪文件在数据库主机上的位置。
  • 通过搜索查询注解字符串来查找.trc文件
  • 从OS命令行使用TKPROF实用程序处理跟踪文件-“tkprof filename.trc tkprof filename.out“
  • 检查/发布您看到的执行路径和时间。
jmp7cifd

jmp7cifd3#

检查以确保没有人设置属性oracle.jdbc.defaultNChar=true
有时候这样做是为了解决unicode问题,但这意味着所有列都被视为nvarchars。如果你有一个varchar列的索引,它不会被使用,因为oracle必须使用一个函数来转换字符编码。

bbmckpt7

bbmckpt74#

这实际上是一个与ORACLE服务器端配置有关的问题,如果origin是FORCE,只需将Cursor_Sharing更改为EXACT即可

相关问题