我目前面临的问题是,在我的Java应用程序中,特定的SQL查询需要大约30秒才能发出,而在SQL客户端(SQL Developer)中则需要<1秒.
在问题中,
JDBC中的Java查询慢而不是其他系统(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'))
Run Code Online (Sandbox Code Playgroud)
其中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中工作?
由于特定表上的全表扫描,我的进程表现不佳.我已经计算了统计数据,重建了现有的索引,并尝试为此表添加新索引,但这还没有解决问题.
隐式类型转换可以停止使用索引吗?其他原因呢?全表扫描的成本比索引查找大1000左右.
编辑:
SQL语句:
select unique_key
from src_table
where natural_key1 = :1
and natural_key2 = :2
and natural_key3 = :3;
Run Code Online (Sandbox Code Playgroud)
Java代码(不易修改):
ps.setLong(1, oid);
Run Code Online (Sandbox Code Playgroud)
这与列数据类型:varchar2冲突