我目前面临的问题是,在我的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中工作?
答案 0 :(得分:2)
我会尝试在使用该应用程序时在数据库上运行trace。
然后您应该能够看到正在运行的查询以及实际的执行计划。这将向您显示正在发生的事情,即它是否正在拾取索引。
答案 1 :(得分:1)
由于传入了谓词,很可能会遇到绑定变量峰值问题。尝试使用以下命令运行查询以确认(即一致的运行时间)
alter session set “_optim_peek_user_binds”=false;
所有对象的统计数据都是最新的吗?
正如Justin发布的那样,确保您也正确测量。如果没有完整的查询,将很难提供额外的见解。
答案 2 :(得分:0)
检查以确保某人未设置属性oracle.jdbc.defaultNChar = true
这有时会解决unicode问题,但这意味着所有列都被视为nvarchars。如果varchar列上有索引,则不会使用它,因为oracle必须使用函数来转换字符编码。