休眠查询运行缓慢

pla*_*eon 5 performance oracle oracle-11g

我目前面临着从 Java 程序启动的运行缓慢的 Hibernate 查询的问题。它在后端调用 Oracle 11g。

此查询在第一次运行时需要 40-90 秒。然而,在随后的执行中,查询会在很短的时间内返回(我什至没有看到数据库被命中,因此假设休眠正在缓存它)。

如果我将查询从企业管理器复制并粘贴到 SQL 客户端并直接运行相同的查询(甚至更改一些参数),查询将在几分之一秒内返回。

如果我查看 EM 中的性能调整选项卡,我会发现所花费的时间主要用于用户 I/O 等待 (97.5%) 和 CPU (2.5%)。这是否意味着我在休眠中使用的提取大小配置的值太小?

如果您可能需要任何其他信息来帮助我深入了解此问题,请告诉我。

======

附加信息:

我们确实在表上有一个索引,我可以看到它被用作查询执行的一部分,不幸的是它不是很可读,但我不确定如何包含它:

Id  Operation   Name    Rows
(Estim)     Cost    Time
Active(s)   Start
Active  Execs   Rows
(Actual)    Read
Reqs    Read
Bytes   Mem
(Max)   Activity
(%)     Activity Detail
(# samples)
0   SELECT STATEMENT                        1                       
1   . FILTER                        1                       
2   .. HASH JOIN RIGHT OUTER        2674    7223    1   +4  1   0           1M      
3   ... TABLE ACCESS FULL   TOTEM_EQ_EXPIRYCODES    475     4   1   +4  1   481                     
4   ... HASH JOIN RIGHT OUTER       2674    7219    1   +4  1   0           399K        
5   .... TABLE ACCESS BY INDEX ROWID    TOTEM_EQ_UNDERLYINGS    1   2   1   +4  1   1                   
6   ..... INDEX UNIQUE SCAN     TOTEM_EQ_UND_PK     1   1   1   +4  1   1                   
7   .... NESTED LOOPS                       1                       
8   ..... NESTED LOOPS      2674    7216    42  +4  1   0                   
9   ...... TABLE ACCESS BY GLOBAL INDEX ROWID   EQUITIES_MONTHLY_INSTRUMENTS    2671    1871    45  +1  1   8438    3517    27MB        24.44   db file sequential read (11)
10  ....... INDEX RANGE SCAN    EQ_MON_INS_UNDERLYING_INDX  2671    12  42  +4  1   8438    27  216KB           
11  ...... PARTITION RANGE ITERATOR         1   2           8438                        
12  ....... INDEX RANGE SCAN    EQ_MON_RESULT_INSPT_UNQ     1   2   44  +2  8438    0   5403    42MB        75.56   Cpu (1)
db file sequential read (33)
13  ..... TABLE ACCESS BY LOCAL INDEX ROWID     EQUITIES_MONTHLY_RESULTS    1   3                   

Here are the Global stats:

Elapsed
Time(s)     Cpu
Time(s)     IO
Waits(s)    Fetch
Calls   Buffer
Gets    Read
Reqs    Read
Bytes
45  0.73    45  1   22980   9740    76MB            
Run Code Online (Sandbox Code Playgroud)

pla*_*eon 1

事实证明,问题与选择作为查询计划一部分的索引有关。

该查询接受一个范围作为其参数集的一部分。由于我现在不打算讨论的原因,我们将范围开始日期和结束日期传递为相同的值。

当我们直接进行调用时,我们对这些参数进行硬编码,Oracle 推断它们代表单个日期,而当通过代码传递它们时,范围作为绑定变量传递。

这意味着 Oracle 选择在一种情况下扫描所有分区,而在另一种情况下选择扫描特定分区。

我们最终通过仅传递一个日期参数来修复查询,因为我们意识到我们不需要范围!

诚然,这是一个相当特殊的情况!