2015-09-15 18 views
7

Oracleデータベースに対する休止状態のクエリで数日間苦労しています。 このようなものは、グリッドにレコードを供給するために使用されます。Hibernateのパラメータ化されたsqlクエリの低速でアクティブなOracleセッション

SELECT 
    fields 
FROM 
    tables and JoinedTables 
WHERE 
     Field1 >= :value1 
    AND Field2 = :value2 
    AND Field3 = :value3 
Order By MaintTable.Id Desc 

このアプローチをSpringのJava + Hibernate 4.2メソッドで使用する。

SQLQuery query = (SQLQuery) session.createSQLQuery(querySql) 
           .addEntity(CertificateViewEnt.class) 
           .setParameter("value1", firstCertificateRecordDate) 
           .setParameter("value2", certType.toUpperCase()) 
           .setParameter("value3", deleted? 1:0);  

すべてのフィルタリングされたフィールドは正しく索引付けされ、パフォーマンスを向上させるためにMaintable.Id Descendentのファンクション索引が作成されます。

)(最初は私はそれがセッション/接続プールが正しく管理されていないと思ったので、私はStatelessSessionに変更し、このsession.closeを追加します。

query.setCacheable(false) 
       .setTimeout(30) 
       .setReadOnly(true); 
... 
... 
//Pagination 
query.setMaxResults(rows); 
query.setFirstResult(HelperMethod(page, rows)); 

result = (List<CertificateViewEnt>) query.list(); 
session.close(); 
return result; 

それはそれを解決しませんでした。 クエリーは何回か実行されますが、何らかの不明な理由があり、以前に成功して実行されていた値を使用してハングし、セッションがOracleでオープンされます(status = ACTIVE)。 任意のSQLクライアント上でOracleに対して同じクエリを実行し、可能なすべての組み合わせのparamsを使用して何回も実行すると、一度に10レコードにつき約400msという極端なパフォーマンスで実行されます。ここにあるいくつかの記事を読んだ後

、 リンク1 [Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query リンク2:[query hangs oracle 10g

私は、Hibernateが使用されて不十分なクエリ実行計画のsupectedとバインドされたパラメータを使用して、すべてのフィルタを削除することを決定しても解決しませんでした少し上手くいったけど。 1ページのような他のページに移動するときに絞首刑しばらくして、2,3,4、...すべてのその後

、私はHibernateのメソッド

query.setMaxResults(rows) 
query.setFirstResult(SomeHelperMethod(page, rows)); 

によって生成されたSQLの疑い見たので、ログ内のその彼らバインド・パラメータとしてOracleに渡されていました。

 ... 
     Order By Certificado.Id Desc) row_ 
     where rownum <= ?) 
    where rownum_ > ? 

私はまた、トレースログ

2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX(

と、この中でこれを見た:

2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [2] as [VARCHAR] - E 
2015-09-15 14:09:53 DEBUG Loader:2031 - bindNamedParameters() 0 -> deleted [3] 
2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [3] as [INTEGER] - 0 
2015-09-15 14:09:53 TRACE Loader:1931 - Bound [7] parameters total 
/* 
SLOW here !!! Around 3 secs when query runs in ~0,300 secs via SQL client. 
And ACTIVE sessions are left running in Oracle. 
*/ 
2015-09-15 14:09:56 TRACE JdbcCoordinatorImpl:397 - Registering result set [[email protected]] 
2015-09-15 14:09:56 TRACE Loader:943 - Processing result set 

は、最後に私はすべてのHibernateバインドのparamsおよび実装カスタム計算ページネーションを放棄しなければならなかったし、すべてのSQLを書きましたページ行を取得し、dbセッションを正しく実行して管理しています。

だから、私の質問は:は、それがデータベースに対して実行されるように実行するクエリを防ぐシーンをbehingやって休止状態とは何ですか ? バインドパラメータクエリには既知の問題はありますか?

私は本当にすべてのSQLコードを書いていると私はバインドパラメータを持っているとき、このSQLをハード解析することを強く勧めません。

環境に関する注意: TomcatとOracleは同じホスト上にあります。そうネットワーク接続が問題

Hibernateのバージョン4.2.15最終

テーブルがDEVデータベース(製造上の1,5M)の周り300K RECSを有しており、一度に10、20、50 RECSのページを示すありません主キーDesc(シーケンス生成)によってソートされました

Hibernateの専門家の中には、大規模なデータベースプロジェクトでHibernateのクエリを依然として信頼できるように、私がこれを手伝ってくれることを願っています。 ありがとうございます。

+0

同じ問題があります。 MySQL Workbenchでは、クエリは0ミリ秒かかります。 Hibernateでは1500msかかる。 –

+0

すべてのHibernateパラメータを取り出し、SQL文字列に設定されているすべてのパラメータを使用して、すべて自分でSQLクエリを構築します。 それは私のために働いた。 JDBCの古い学校のクエリと同じように。 –

+0

チップをありがとう。間違いなく試してみる価値がある! –

答えて

1

これは問題であるかどうかわかりませんが、Oracleは問合せの解析時にバインド変数の値を調べ、将来の実行のために問合せ計画を保存して、毎回問合せを解析する必要はありません。バインド変数の新しいセットで実行します。しかし、何度もクエリが再解析されます。解析中に異常なバインド変数値が渡された場合、悪い計画が格納されて使用されます。バインド変数の呪縛のようなものです。解析を減らすことができますが、クエリが再度解析されたときに、非典型的なバインド変数値に基づいてプランを反転させることができます。ヒントが役立ちます。 SQLプロファイルを使用して、プランを変更する傾向のあるバインド変数を使用したクエリのプランをロックします。場合によっては、オプティマイザ統計が収集される時期と方法をカスタマイズして、バインド変数に渡す値に関係なく適切なプランを作成することができます。

とにかく、何か私はいつも見るもので、あなたの問題かもしれません。

ボビー

関連する問題