15

Oracle の休止状態およびネイティブ クエリでパフォーマンスの問題を検出しました。TOAD で複数のパラメーターを使用して複雑な SQL クエリを実行すると、ミリ秒単位で結果が得られます。ただし、Hibernate を使用して同じクエリを実行すると、この時間が大幅に増加します (最大 4 秒またはそれ以上)。

私の SQL クエリはかなり複雑で、一意の値を返します (したがって、問題はクラスのインストールに必要な時間とは関係ありません)。「:nameParameter」という形式のパラメーターがいくつか含まれています。このクエリは文字列に格納されます。例えば、

String myNamedNativeQuery = "select count(*) from tables "+
                            "where column1 = :nameParameter1 "+ 
                            "and column2 = :nameParameter2";  
                            //actually my sentence is much more complex!!

TOAD で文を実行すると、数ミリ秒で解決されます。しかし、この文を Hibernate で使用する

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");

query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);

query.uniqueResult(); 

同じ結果を得るには数秒かかります。

ネイティブクエリでパラメータを直接置き換えてから、Hibernate を使用して文を実行すると、時間が大幅に短縮されることに気付きました。それは次のようなものです:

String strQuery = session.getNamedQuery("myNamedNativeQuery").getQueryString();

myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter1", value1);
myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter2", value2);

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.uniqueResult(); 

何が起こっているか知っている人はいますか??

前もって感謝します。

PS: Oracle のバージョンは 9i で、Hibernate 3.2 です。

4

3 に答える 3

7

このコードで何が起こっていると思います:

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);
query.uniqueResult(); 

これは:

1 行目: 名前付きパラメーターの予期される値に基づいて、クエリ プランが作成されます。

行 4 : クエリは value1 と value2 で実行されますが、これらの値は行 1 で精巧に作成されたクエリ プランの「適切な値」ではないため、データベースは実際の値に対して非常に不適切なプランを実行しています。多くの時間。

なんで ?

のソースコードを見ると、HibernateSessionImpl.createSQLQuery(...)次のコード行が見つかりました。

SQLQueryImpl query = new SQLQueryImpl(
                sql,
                        this,
                        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
        );

これは、いくつかの parameterMetaData で呼び出しgetQueryPlanCache()ています。このメタデータは十分ではないと思います。

于 2013-01-12T16:05:57.687 に答える
0

あなたへの私の答えは次のとおりです。

すべてのバインド パラメータを削除し、Session の代わりに StatelessSession を使用します

パラメーター値を含む完全な SQL を使用したクエリの代わりに SQLQuery を使用する

StatelessSession session = sessionFactory.openStatelessSession();

私は同様の問題を抱えていましたが、より良い解決策が得られるまで、これがうまく機能するようになりました。Hibernate のパラメーター化された SQL クエリの低速でアクティブな Oracle セッションを参照してください 。

于 2015-09-15T22:39:35.967 に答える