8

それは私を夢中にさせています。Navicatを介して直接クエリを実行する場合と比較して、Hibernateの単純な選択を行うのは非常に時間がかかります。もっと興味深いものは何ですか。ローカルデータベースでこのクエリを実行するのは非常に高速ですが、リモートで使用するのは非常に貧弱です。

私は次のHibernateネイティブSQLクエリを実行しています(HQLまたはCriteriaは左結合をサポートしていないため):

List list = new ArrayList();
String queryStr = "select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null";
Query query = session.createSQLQuery( queryStr ).addEntity( SalesUnit.class );

Long start = System.currentTimeMillis();
list.addAll( query.list() );
Long stop = System.currentTimeMillis();
System.out.println( "Time: " + (stop - start) + "ms." );

エンティティの構造は実際には重要ではありません。SALES_UNITテーブルとSALES_UNIT_RELATIONテーブルの両方に約28kのレコードがあります

ローカルデータベースを使用してローカルJBossで実行した結果は、約30〜120ミリ秒です。リモートデータベース、ローカルJBoss(同じデータ)で実行している場合、時間は30000〜40000ミリ秒になります。Navicatでこのクエリを実行しているとき、ローカル呼び出しとリモート呼び出しの両方が非常に高速です(20〜30ミリ秒)。

ローカルデータベースとリモートデータベースの両方が同じ方法でインストールされました->OracleEnterpriseEdition11.2.0.1.0。

このようなパフォーマンスの低下の問題は何でしょうか?どうすればデバッグできますか?

これを読んでください:単純な休止状態のクエリは非常にゆっくりと返されますが、コンストラクターを設定しても何も変更されませんでした

編集。

SALES_UNITテーブルには、名前などの販売単位ノードに関する基本情報が含まれています。唯一の関連付けは、ManyToOneとしてのテーブルSALES_UNIT_TYPEです。主キーはIDであり、日付であるフィールドVALID_FROM_DTTMです。

SALES_UNIT_RELATIONには、販売単位ノード間のリレーションPARENT-CHILDが含まれています。SALES_UNIT_PARENT_ID、SALES_UNIT_CHILD_ID、およびVALID_TO_DTTM/VALID_FROM_DTTMで構成されます。テーブルとの関連付けはありません。ここでのPKは、.. PARENT_ID、.. CHILD_ID、およびVALID_FROM_DTTMです。

4

2 に答える 2

3

助けてくれてありがとう。その問題に長い間苦労した後、ついにkaliatechの回答が問題のデバッグに役立ちました。

まず第一に、私は私の質問でひどい間違いをしました。私はそれを書いた:

ローカルデータベースでこのクエリを実行するのは非常に高速ですが、リモートで使用するのは非常に貧弱です。

それは完全に真実ではないので。Hibernateで行ったクエリは次のようになります。

select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null

しかし、たとえばSQLPLusやNavicatで行った実際のクエリは次のとおりです。

select * from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null

select s.* ...最初のクエリ選択が開始され、2番目のクエリが。であることに注意してくださいselect * ...。そして、それがそのようなパフォーマンスの低下の理由でした。これで、両方のクエリがすぐに完了します。問題は、違いは何ですか:パフォーマンスの問題:selects。*とselect*の違い

于 2012-11-15T13:15:18.717 に答える
2

決定的な答えを得るには、もっと多くの情報が必要だと思います。主に:

  • SalesUnitエンティティクラスにエンティティの関連付けまたはコレクションフィールドがありますか?<-これは、他の情報の代わりに見られるパフォーマンスの違いについての私の最初の推測です。

  • 非Hibernate環境で同じJDBCドライバーを使用してクエリを実行すると、同じパフォーマンスの問題が発生しますか?(つまり、 DbVisualizerなどのサードパーティのJDBCクライアントを使用します)。

また、

質問の情報で確実に知ることは不可能ですが、子のSalesUnitを持たないすべてのSalesUnitをクエリしたいと思います。正しい?(sales_unit_relationテーブルを何に使用しているかによって異なります。)その場合、クエリは次のように記述します。

String queryStr = "select s.* from sales_unit s
                   left join sales_unit_relation r on 
                   (s.sales_unit_id = r.sales_unit_child_id)
                   where r.sales_unit_child_id is null";

しかし、私はあなたがおそらくこのような何かを望んでいたと思います:

String queryStr = "select s.* from sales_unit s
                   left join sales_unit_relation r on 
                   (s.sales_unit_id = r.sales_unit_id)
                   where r.sales_unit_child_id is null";

現状では、クエリはWHERE句でnullをフィルタリングする列に対して結合しています。それが本当にあなたが望んでいたものであるなら、WHERE句なしでINNERJOINとしてそれを書くこともできたでしょう?

最後に、

次のHibernateネイティブSQLクエリを実行しています(HQLまたはCriteriaは左結合をサポートしていないため)

述べたようにそれは正しくありません。HQLとCriteriaは、クエリ対象のエンティティ/テーブル間にマップされた関係がない場合にのみ、左結合をサポートしません。したがって、あなたの例による仮定は、SalesUnitとsales_unit_relationテーブルが表すエンティティ/アソシエーションとの間にマップされたエンティティ関係がないということです。(ネイティブクエリは関係なく機能するはずですが、マップされた関係があった場合、HQL / Criteriaを使用する利点の1つは、実行できることですleft join fetch。)

于 2012-11-14T16:45:53.997 に答える