A. SQLクエリの休止状態N + 1問題-------反復
検索するには2つの方法があるときibernate session.createQuery(HQL)クエリデータを使用します。
クエリは一度だけ、すべてのデータは、両方の、その背後にあるデータへの直接アクセスをチェックアウト照会されます。
入手:session.createQuery(HQL)の.listを()。
データ、低効率、例えば、商品情報表示の使い捨てローディング。これは、すべての情報の表示に適用されます。
2、他は後でデータを必要なときに、主キーは、主キー内のデータへのアクセスをチェックするクエリです。
入手:session.createQuery(HQL).iterateを()。
ショーのニュース一覧。あなたは、主キーに基づいてデータを照会するために特定のコンテンツには、ニュースコンテンツを表示する必要がある場合。
これは、1つまたは少数のショーのメッセージに適用されます。
第二に、JavaのキャッシュシステムJCS(Javaキャッシュシステム)について教えてください
1、JCS(Javaのキャッシュシステム)は、オブジェクトキャッシュ、アクセスJavaオブジェクトの高頻度にアクセスし、それらの効率を改善するためにキャッシュできるJavaオブジェクトであります。JCSに応じ一意のオブジェクトにアクセスするためのオブジェクトを識別し、そのようなオブジェクトは従っのハッシュコードにアクセスすることができます。
2は、休止状態のため、JCSは、キャッシュクエリーの結果に使用され、そのときに、同じデータへの次の訪問することができ、あなたは、クエリの速度を加速するために、JCSから直接取られたデータベースを、取る必要があります。
最初にデータを読み出すために休止状態リストまたはイテレータの方法を使用して、JCSが空のとき3、次いで、リストモードまたはイテレータの方法のいずれかは、JCS永続オブジェクト、内部に充填をチェックアウトすることで
catからCを選択して次のようなCなど
を選択c.id、POに構成されていないので、JCSを埋めるためではないHQL文のCのような猫からc.name。
図4は、領域からJCSのデータ:
マスター鍵リストに従って一意にアクセスされるオブジェクトを識別し、そしてPO永続オブジェクトのために、一意の識別子が主キーであり、Hibernateは最初にプライマリキーのリストを取得しなければならない応じてJCSからデータをフェッチし、次に一つずつ決意は、データベースは、その後、SQL取ら送信する場合、内部JCS場合、次いで、JCS内部マスターキーに応じて取らこの永続オブジェクトかどうかをデータベースに参照します。
5、リストはできませんが、ここでイテレータを教えするには、JCSを使用することができます。その上で、JCSを使用する前に、最初にデータベースに対して行われなければならない主キーのリストを取得するために、JCS永続オブジェクトの内部で取得するために、永続オブジェクトの主キーを取得する必要があり、このステップでは、バッファリングする方法はありません。
二、リストと異なる形で反復クエリデータ:
図1に示すように、クエリ自体の休止イテレータを2つの段階に分けられる:N + 1問題の存在が
==> // catからIDを選択
==> SELECT * FROM猫IDから = // n個の記事?
分析:第一工程、 、主キーのリストを取得するためのデータベース
フェッチデータの主キーに従って、第二工程。JCSはない場合には、N + 1回のSQLクエリ、必要がデータベースのnレコードから削除
しますが、JCS、JCSを使用した場合、彼は最初の直接を取る場合があり、主キーに基づいて永続オブジェクトを探し、内部の見てみましょう以下とから、いない場合は、その後、私はJCSが中に入る埋めるためにそれを送信する前に、データベースを取りに行く必要がありました。
2、および休止状態リストモード:
==> SELECTからのCATは、*
これは、SQLは、すべてのデータを取り出して置いたら、それは、イテレータのように最初の主キーを取り、その後、データを取るので、できなかっ一覧ませんでした、シンプルなJDBCパッケージですJCSを使用しています。
リストが満たされていてもよいが、データは内部JCSにデータベースから抽出されました。
再度、クエリデータのリストを使用する場合は、まだSQLデータベース、証拠リストを()送信するデータを読み込むキャッシュを使用しない方法
最初のステップ、フェッチデータのプライマリ・キーによれば、第2工程をプライマリ・キーのリストを取得するためのデータベース。何JCSは、あなたがn + 1回のSQLクエリを必要とするデータベースからn個のレコードを削除しない場合はもちろん、私たちは今、イテレータモードで、見ることができ、これは非常に恐ろしいことなので、JCSの使用がなければ、また、あなたはIteratorを使用しないようにする必要があり、大量のデータを拾う必要があります。
イテレータの最初のSQL主キーは、リストを取ることです、この時間の消費量は、あなたがJCSを使用している場合、そのたびにクエリがSQLを送ることが避けられないことはまだある、非常に小さい:プライマリキーのリストを取得するためにcatからIDを選択し、それ?その後、イテレータはそれほど愚かではありません、彼はまず、あなたが直接を持っている場合ではない、その後、データベースを取りに行く必要があった場合は、主キーに基づいて永続オブジェクトを探し、JCSの内側を見て埋めるためにそれを置くだろうJCSの内側へ行きます。
後でそれを見ることができる、JCSは、メモリ内のシンプル・オブジェクト・データベースに多少似ている、最初のイテレータは、一度プライマリキーのリストを取得するSQL取っ内のデータベースに行く必要不可欠である、キー、イテレータが最初というJCSを開こうとすることを主キーを作りましたロック、開いていない場合、我々はデータベースのロックを開くために持っていた、直接にオープンを打ちます。
JDBCやHibernateはリストは、すべてのデータを取り出す入れSQLをパッケージ化するための簡単な方法ですが、それは、イテレータのように最初の主キーを取り、その後、データを取るので、リストJCSを使用することはできませんしませんでした。リストが満たされていてもよいが、データは内部JCSにデータベースから抽出されました。
最善の方法:リストを使用するには、最初の訪問、迅速JCSを埋めるには、Iteratorを使用してアクセスした後、JCSをフルに活用します。
mikeho書き込み:
それはどのようにJCSデータベースであるとペースを保ちますか?
ロビンの書き込み:
jcs.default.elementattributes.MaxLifeSeconds = 240(最大バッファ時間)
脇に行うためのタイムアウトを設定し、プラスあなたは、プログラムの内部も明らかJCSキャッシュすることができます
三、リストおよびオブジェクトの反復分析戻る:
リストリターンは()エンティティオブジェクトであり、オブジェクトの反復()プロキシオブジェクトを返します。
https://blog.csdn.net/liumuqi110/article/details/4625055
キャッシュケースを使用して、4つの、リストと反復
図1は、反復は、(クエリキャッシュは、次に、オンになっている場合)のみクエリキャッシュを使用するリストセッション・キャッシュ、レベル2キャッシュを照会する
クエリキャッシュがオンになっている2は、の反復とリストクエリに影響
クエリキャッシュが既に開かれている:クエリキャッシュキャッシュは、クエリ、そのようなキー値ではなく、クエリ結果は、セッションキャッシュと二次キャッシュに配置され.queryの結果として、ページング情報を、一緒にパラメータを使用して、生成されたSQL HQLにクエリ自体と。キャッシュは、分化している
構成クエリキャッシュ:オープンクエリキャッシュ:1、コンフィグhibernate.cache.use_query_cacheに設けられ=真、2、クエリ後に作成query.setCacheable(TRUE);
以下を開くためにキャッシュクエリであります:いくつかのシナリオのリストが
1:
クエリQ1 = s1.createQuery( "com.test.hb.Hbtest Hからここh.id <3")。
q1.setCacheable(真の);
クエリQ2 = s1.createQuery( "h.id = 1 com.test.hb.HbtestからH")。
q2.setCacheable(真の);
論理的には、最初のクエリのクエリは、値が2番目のクエリが含まれている必要がありますが、2番目のクエリは、キャッシュクエリを使用しませんが、データベースを再照会します。
2:
クエリQ1 = s1.createQuery( "からcom.test.hb.Hbtest Hここh.id = 1")。
q1.setCacheable(真の);
クエリQ2 = s1.createQuery( "h.id = 1 com.test.hb.HbtestからH")。
q2.setCacheable(真の);
二つの同一のクエリは、2番目のクエリは、キャッシュクエリを使用し、データベースを再照会しません。
3:
クエリQ1 = s1.createQuery( "からcom.test.hb.Hbtest Hどこh.id =?")setInteger(0、1)。
q1.setCacheable(真の);
クエリQ2 = s1.createQuery( "com.test.hb.Hbtest Hからh.id =?")setInteger(0,1)。
q2.setCacheable(真の);
二つのクエリが同じで、2番目のクエリは、キャッシュクエリを使用し、データベースを再照会しません。
4、
クエリQ1 = s1.createQuery( "com.test.hb.Hbtest Hからh.id =?")setInteger(0,1)。
q1.setCacheable(真の);
クエリQ2 = s1.createQuery( "com.test.hb.Hbtest Hからh.id =?")setInteger(0,2)。
q2.setCacheable(真の);
論理的には、2つのクエリは、2番目のクエリキャッシュクエリを使用しませんが、データベースを再照会し、同じではありません。
イテレータシーンで開いた後にキャッシュを照会:
。クエリキャッシュは、SQLのIDのための最初の時間をキャッシュしません、反復子バックあなたはそれがキャッシュには、データベース内の意思決定のキャッシュアクセスイテレータよるセッションには影響を与えません照会すると言うことができるとき。
**キャッシュはネイティブSQLの場合は、2つのクエリのSQL文は、二回のデータベースにアクセスし、次の例のように(場合を含む)は同じでなければなりません。
ローカルSQL:
クエリQ1 = s1.createSQLQuery SELECTから(「ヴァルWHERE h.id. 1 = H Hbtest ");
クエリs1.createSQLQuery Q2 =(" Hbtestヴァルから選択WHERE h.id = H. 1「)。
HQLは、HQLをSQLに変換されます冬眠しないために、このプロセスは「識別」されます同じSQLではありません。次の例では、データベースに一度のみアクセス可能です。
com.testからクエリs1.createQuery Q1を=(」 WHERE h1.id. .hb.Hbtest 1 = H1 ");
クエリs1.createQueryのQ2 =(" com.test.hb.Hbtest = H. 1からh.id「)。
五、和リストを反復的使用情况:
反復:
)(S1 = sessionFactory.openSessionと、
クエリQ = s1.createQuery( "com.test.hb.Hbtest Hからここh.id <2")。
ITRはq.Iterator()=イテレータ。
一方、(itr.hasNext()){
Hbtest TBO =(Hbtest)itr.next();
}
リスト:
反復:
S2 = sessionFactory.openSession();
クエリQ = s2.createQuery( "com.test.hb.Hbtest Hからここh.id <2")。
リストLS = q.list();
int型私= 0;
一方、{(iはls.size()<)
Hbtest TBO =(Hbtest)ls.get(I)。
I ++;
}
両方の形態の組み合わせを使用して:
S1 = sessionFactory.openSession();
クエリs1.createQuery Q =( "com.test.hb.Hbtest H <2からh.id");
リストq.listのL =() ;
イテレータl.iterator ITR =();
一方(itr.hasNext()){
Hbtest TBO =(Hbtest)itr.next();
}
リスト()メソッドは、すべての結果がオブジェクトを設定すると撮影されます、そして、彼は、クエリに基づいて行われます結果は、結果セットのすべてのオブジェクトを初期化します。それは多くのメモリを占有した場合、結果セットが非常に大きく、メモリオーバーフローが発生しても原因とき。
イテレータ()メソッドは、一度オブジェクトのすべての実装で初期化されませんが、結果セットへの訪問に基づいてオブジェクトを初期化します。最初の訪問では、メモリオーバーフロー状態を引き起こし、あまりにも多くのキャッシュを消費避けるために、キャッシュ内のオブジェクトの数を制御することができます。
オリジナルリンク:http://www.linuxidc.com/Linux/2012-01/52003.htm