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
問題は、クエリプランの一部として選択されていたインデックスに関係していることがわかりました。
クエリは、一連のパラメータの一部として範囲を受け入れていました。理由は今は入りませんが、範囲の開始日と終了日を同じ値に渡しました。
直接呼び出しを行っているときは、これらのパラメーターをハードコーディングしており、Oracleはそれらが単一の日付を表していると推定していました。
つまり、Oracleは、あるケースではすべてのパーティションをスキャンし、別のケースでは特定のパーティションをスキャンすることを選択しました。
範囲が必要ないことに気付いたので、最終的には単一の日付パラメーターを渡すだけでクエリを修正しました。
確かにかなり独特な状況!