web-dev-qa-db-ja.com

Hibernateクエリの実行が遅い

Javaプログラムから開始されている、実行速度の遅いHibernateクエリの問題に直面しています。バックエンドでOracle 11gを呼び出しています。

このクエリは、最初の実行時に40〜90秒かかります。しかし、その後の実行では、クエリはほんの少しの時間で返されます(データベースがヒットしているのを見さえしないので、Hibernateがそれをキャッシュしていると仮定します)。

Enterprise ManagerからSQLクライアントにクエリをコピーして貼り付け、まったく同じクエリを直接実行すると(いくつかのパラメーターを変更した場合でも)、クエリはほんの一瞬で返されます。

EMの[Performance Tuning]タブを見ると、主にユーザーI/O待機(97.5%)とCPU(2.5%)に時間がかかっていることがわかります。これは、Hibernateで使用しているフェッチサイズの設定値が小さすぎることを意味しますか?

この問題の原因を突き止めるのに役立つその他の情報がある場合は、お知らせください。

=====

追加情報:

テーブルにインデックスがあり、クエリの実行の一部として使用されていることがわかります。残念ながら、あまり読みにくいですが、他にどのように含めるかわかりません。

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            
5

問題は、クエリプランの一部として選択されていたインデックスに関係していることがわかりました。

クエリは、一連のパラメータの一部として範囲を受け入れていました。理由は今は入りませんが、範囲の開始日と終了日を同じ値に渡しました。

直接呼び出しを行っているときは、これらのパラメーターをハードコーディングしており、Oracleはそれらが単一の日付を表していると推定していました。

つまり、Oracleは、あるケースではすべてのパーティションをスキャンし、別のケースでは特定のパーティションをスキャンすることを選択しました。

範囲が必要ないことに気付いたので、最終的には単一の日付パラメーターを渡すだけでクエリを修正しました。

確かにかなり独特な状況!

0