我目前面临的一个问题是,从Java应用程序中发出一个特定的SQL查询大约需要30秒,但在SQL客户端(SQL Developer)中却不到1秒。
在这个问题上,
Slow query in Java by JDBC but not in other systems (TOAD),建议使用绑定到java变量的PreparedStatement可能会使查询的执行速度远远慢于在SQL客户端(在这种情况下为TOAD)中的执行速度,因为Oracle对使用哪些索引感到困惑。不带参数的PreparedStatement是否也会出现此问题?
否则会有什么问题?
查询类似于
select
sum(col1),
sum(col2),
max(select ...)
from view_
where time_id = get_time_id(to_date('2010-10-10','yyyy-mm-dd'))
字符串
其中view_是一个复杂视图,包含表和其他复杂视图的聚合。查询作为PreparedStatement执行,但不带任何参数。使用预准备语句还是仅使用普通语句似乎没有区别。
由于执行计划是相当巨大的,我不能张贴所有如果它在这里,但相关的区别似乎是:
UNION-ALL
TABLE ACCESS FULL GVC_WH.PLAYER_FACT_DAILY TABLE 37 6717151 596,934.317 19940 240 7621178231 19502
UNION-ALL
TABLE ACCESS BY INDEX ROWID GVC_WH.PLAYER_FACT_DAILY TABLE 38 2657 236.120 2429 30 20544658 2428
INDEX RANGE SCAN GVC_WH.PK_AGG_PLAYER INDEX (UNIQUE) 37 2657 16 1 638743 16
的数据
其中第一个代码段是在JDBC瘦客户机上运行的,第二个代码段是在SQL Developer中运行的。在JDBC瘦客户机上作为语句运行时,它没有选择正确的索引(无论是否使用预处理语句都没有区别)。第一个代码段的时间差是30秒,第二个代码段的时间差是0.5秒。
使用函数get_time_id是否会禁止在通过JDBC使用索引时使用该索引,即使它不是列上的函数,即使它似乎在SQL Developer中工作?
4条答案
按热度按时间vcudknz31#
我会尝试在使用应用程序的同时在数据库上运行trace。
然后你应该能够看到正在运行的查询,以及实际的执行计划。这将告诉你到底发生了什么,即它是否正在拾取索引。
7hiiyaii2#
由于传入的 predicate ,您很可能会遇到绑定变量峰值问题。尝试运行以下查询以确认(即一致的运行时间)
字符串
所有对象的统计数据都是最新的吗?
正如justin所说的,确保你的测量是正确的,如果没有完整的查询,就很难提供更多的见解。
sqxo8psd3#
检查以确保没有人设置属性oracle.jdbc.defaultNChar=true
有时候这样做是为了解决unicode问题,但这意味着所有列都被视为nvarchars。如果你有一个varchar列的索引,它不会被使用,因为oracle必须使用一个函数来转换字符编码。
vmjh9lq94#
如果origin是FORCE,只需将Cursor_Sharing更改为EXACT