- PR -

セッションに登録された大量データを削除するタイミング

投稿者投稿内容
ゆう
常連さん
会議室デビュー日: 2001/12/10
投稿数: 33
投稿日時: 2004-02-09 13:03
検索条件に合致するデータが多い場合に以下のようなページ制御の方式を考えています。

1、検索条件に合致したデータを全て取得し、HTTPセッションに登録する
2、一画面に表示する件数のみのリストを別途作成し、画面に表示する
3、ページ制御ボタン(例えば"次ページ")が押下されるたびに、
  上記1で登録したHTTPセッションデータを取り出し、上記2の処理を行なう。

この場合にセッションに登録されたデータをセッションから削除するタイミングに関して
どのようにされているのかを教えてください。

現状では、ログアウト時とメニューからの遷移の場合に削除することを考えていますが
いかがでしょうか?

※一覧画面からは詳細画面等へリンクが貼ってあり、
 その詳細画面から戻るボタンで再度一覧に戻る等の遷移も考えています。

動作環境を以下に示します。
・OS:Win2000
・Servlet Container:Tomcat4.1.27
・その他:struts1.1
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-02-09 14:12
セッションに大きなオブジェクトを登録するのはお勧めしません。ユーザの数に応じてメモリを大変消費してしまうだとか、クラスタ構成時にセッション状態のレプリケートのコストが大きくなってしまうからです。

今回の場合は検索条件だけをセッションに保持して、どのページを表示するかを Action で判定して適切な SQL で必要なデータだけを取得して表示するのが良いでしょう。
Oracle なら rownum 、PostgreSQL なら offset/limit などを使うと欲しい行だけを取得できます。

どうしてもセッションに全部つめこみたいのであれば、フィルタをつかって、一覧表示でない URL へのリクエスト時に removeAttribute すれば良いかと。

[ メッセージ編集済み 編集者: インギ 編集日時 2004-02-09 14:28 ]
ゆう
常連さん
会議室デビュー日: 2001/12/10
投稿数: 33
投稿日時: 2004-02-09 23:35
インギ様、返信ありがとうございます。
確かにセッションに大きなオブジェクトを登録しないに越したことはないのですが、
必要なデータだけを取得するやり方の場合、次ページなどのボタンを押すたびに、
合計件数が変わったりすることが考えられます。(裏では挿入/更新処理が行われているため)
ようは毎回最新表示しているのと同じになります。
これはそのようにすることが却って一般的なのでしょうか?
さくらー
会議室デビュー日: 2003/04/20
投稿数: 16
お住まい・勤務地: 住まい:群馬・勤務地:東京
投稿日時: 2004-02-10 02:29
毎回最新表示では無く、最初に獲得した時のデータを使いたいと言う事ですよね。
でしたら、セッションオブジェクトのID(いわゆるセッションID)をキーにした
データベースのテーブルを用意し、そのテーブルには例えばOracleならば
BLOB型とかを定義します。
そして、最初に獲得したタイミングで、そのBLOB型列にデータを入れておきます。
データ自体は、Serializableなクラスにしておきます。
(そうじゃないとテーブルに入れられない)
で・・後は使いたいタイミングでそのテーブルからBLOB型列を引っ張ってきて
それを使えば良いのでは無いでしょうか。

最新のもを使いたいのか、最初に獲得したものを使いまわしたいのかは仕様次第ですので
それに関しては一般的かどうかと言うのは無いと思います。

不確定要素によりサーバーがパンクしないように知恵を絞って作ると言う事が
一般的かと・・。
ゆう
常連さん
会議室デビュー日: 2001/12/10
投稿数: 33
投稿日時: 2004-02-10 10:17
回答有難うございます。
以前作ったシステムでは、社内利用であったことと
同一セッションで単一ウィンドウにする制御を行なっていたため、
ページ制御用のデータをセッションに登録していました。

今回は社外からのアクセスがあるシステムであり、
メモリ消費量が不確定なため、セッションは止めるべきだと
思っています。

一つだけ気になるのですが、
最新のものを使うにしろ、最初に獲得したものを
使うにしろ、ページ制御を行なうたびに毎回DBアクセスが発生し、
パフォーマンスが落ちると思います。
データをキャッシュするなどの方法を考えなければいけないでしょうか?

結局、検索エンジンのようなパフォーマンスが得られれば良いのですが
仕組みをご存知の方はいらっしゃらないでしょうか?
例えば検索エンジン(google等)ではページ制御を行なっていますが
特に遅いとは思いません。
何万というアクセスがあると思うのでセッションに登録しているとは
思えませんし。
顔爺
ベテラン
会議室デビュー日: 2003/10/03
投稿数: 52
投稿日時: 2004-02-10 10:27
引用:

ゆうさんの書き込み (2004-02-10 10:17) より:
一つだけ気になるのですが、
最新のものを使うにしろ、最初に獲得したものを
使うにしろ、ページ制御を行なうたびに毎回DBアクセスが発生し、
パフォーマンスが落ちると思います。
データをキャッシュするなどの方法を考えなければいけないでしょうか?



java.lang.ref.SoftReference を利用するのはいかがでしょうか。
SoftReference を利用すれば、OutOfMemoryError が発生する前に gc される
ことが保証されるメモリキャッシュを実装できます。
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2004-02-10 10:35
以前全く同じものを実装した経験から
アドバイスさせてもらいます。

メモリに結果を入れるのは好ましくありません。
私は失敗しました。

私のケースでは、検索結果として異常に
多いパターンが多発すること。
また、対象ユーザ数が多いことから
即効でメモリがパンクしました。

確かに性能面では、ページ遷移自体は高速です。

何でもトレードオフだと思うのですが
私の場合は、性能よりメモリとなり
rownumを使ったページ毎の件数を取得
する方法に切り替えました。

データが最新のものであるということに関しては
それほど問題性も感じられなかったのでこの
実装にしました。

他に何か良い方法があるのかしら?
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-02-10 10:53
私が以前試したときは、毎回 SQL を投げるからといって特に性能が低下するということはありませんでした。where 句の条件が同じで、rownum でフェッチする行だけを変化させるのであれば DB 的には検索結果のキャッシュからとってくるだけでたいした負荷にはならないと思います。

初回に全ての行をフェッチする方法は、2ページ目以降の遷移は早いかもしれませんが、最初のページの表示が遅くなります。また、検索結果が膨大になると大抵のユーザは2ページ目以降を見もせずに戻ってから検索条件をさらに入力することになると思います。この場合せっかくとってきた2ページ目以降のデータがもったいないです。

ページを切り変えるタイミングで最新のデータが返ってくる、というのは多くの場合はむしろメリットだと思います。

要件上検索した時点での結果が必要なのでしたら、顔爺さんのおっしゃる通り java.lang.ref.* を使うこともできます。もちろん、キャッシュが破棄された場合に再度フェッチする処理を付け加えなければなりません。
こういう場合は EntityBean を使っていれば検索結果はプライマリキーだけを保持して、実際にデータを参照するときに各レコードを select するような作りにできる(というかコンテナがやってくれる)のですが、Tomcat だけではなにかと工夫がいりますね。

[ メッセージ編集済み 編集者: インギ 編集日時 2004-02-10 11:01 ]

スキルアップ/キャリアアップ(JOB@IT)