- 締切済み
Perlで一覧表示
お世話になっております。 Perl初心者で、Java等は少し経験があります。 「検索を行い一覧を表示する」という画面をPerlで作成する際の 作り方について質問させてください。 現在は以下のような構成で画面を作っています。(DBアクセスには DBI を使用しています) ------------------------------ 【DAO的な pm】 引数として検索条件を受け取り、 DB にアクセスし、 $sth->fetchrow_arrayref で取り出した検索結果を ハッシュや配列に詰めて返す 【画面の pl】 上記DAO的な pm を利用して検索結果を受け取り、 それをループで回して一覧として表示する ------------------------------ ただ、これだと配列にデータをため込むので 検索結果が多くなるとメモリをくいそうで気になっています。 (あと後述の方法と比べるとやっぱり遅い気がする…) 他の方が Perl で作った画面を見たところ、以下のような作り方を見かけました。 ------------------------------ 【画面の pl】 画面内で SQL を発行し、 $sth->fetchrow_arrayref で取り出した検索結果を 逐次出力していく ------------------------------ こちらのほうだと、一覧に出すものが多くても 上からパラパラ表示されていくので 閲覧者側のストレスも少ないと思ったのですが、 Perlの作りとしてはこういうほうが一般的なのでしょうか。 なんとなくDBアクセスは汎用的なクラスにしてしまいたい気持ちになるのですが Perlではあんまりそういうことはしない、とかPerlでもするよ、とか ご存じの方がいらっしゃいましたら教えてください。 あとは関数の戻り値として検索結果をごそっと返すのではなくて、 関数の引数として「一件分のデータを受け取るDelegate」を渡してみたらどうだろうかとか思っているのですが 変でしょうか… よろしくお願いします。
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- t-okura
- ベストアンサー率75% (253/335)
最近は、よほど単純なウェブページを作るのでなければ、HTML::Template や Template Toolkit のようなテンプレートエンジンを使い、ページの元になるテンプレートとそこに埋め込む変数の組み合わせでページを作ります。 テンプレートエンジンに繰り返しデータを渡す際は配列にするので、fetchrow_arrayref で一行ずつデータを取り出しても、サブルーチンでまとめて取り出しても同じことだと思います。 パラパラと表示ということでは、ウェブサーバは出力データをバッファリングしてブラウザに返すので、よほど長大なページでないかぎり目立った違いはないと思いますし、そんな長大なページは見たくない(ページ分割して欲しい)でしょう。 メモリについても、DBI は SELECT を実行したときにデータベースからデータを取り出します。fetchrow_arraref ではすでにバッファに取り込まれたデータを参照しているだけなので、大きな差はでないはずです。 まとめて取り込めないくらいデータが多い場合は、SELECT LIMIT OFFSET で一度に取得するデータを制限し、OFFSET をずらしながら順次データを処理することになります。そしてその時は LIMIT や OFFSET を意識しなくてもよいよう > 「一件分のデータを受け取るDelegate」 のようなサブルーチンを用意するとよいと思います。
お礼
回答ありがとうございます。 大変参考になります。 やっぱりテンプレートを使って view と model を分離させるのってPerlでもやるんですね。 # もともと既存画面があり、 # 私は追加画面を作成しているのですが # 既存画面がそういうふうにはなっていないので… Perlのことを聞ける人が周りにいないのでとても助かります。 ありがとうございます。 今回は表示する行数はさほど多くはないのですが、 データがあちこちに散っていて、 ---------------------------------------- DBサーバA のテーブルに対して SELECT foreach (検索結果) { 検索結果の id をキーに DBサーバB のテーブルに対して SELECT 配列に溜める } 配列を返す ---------------------------------------- のようなことをしていてデータを全件取ってくるのが若干遅めです。 # 別のシステムでも使われているテーブルを参照しているので # DB の見直しもむずかしくて… テンプレートエンジンを使っている場合は配列で渡すしかなさそうですが、 今回は幸か不幸かそうではないので 一行取り出して表示、一行分取り出して... にしてみようかと思っています。 「一件分のデータを受け取るDelegate」のパタンをさっきちょっと実験してみたので。 …実験してみたソースを貼りたかったのですが長すぎて貼れませんでした。 前後をはしょるのでわからないかもしれませんが一応貼るだけ貼ってみます。 ------------------------------ ### 今まで自分で書いてた感じ # 取得 my @lst = &DummyDAO::get_list; # 出力 print $header; foreach my $row (@lst) { &view_row($row); } print $footer; ------------------------------ ### 既存画面の書かれ方。 ### 表示の体感速度は速い、でもあんまり好きじゃない print $header; for (my $r = 1; $r <= $row_count; $r++) { sleep($sleep_ms); # 取得dummy my $row = {}; for(my $c = 1; $c <= $col_count; $c++) { $row->{$c} = sprintf("%05d", $r); } # 出力 &view_row($row); } print $footer; ------------------------------ ### こうしてみようかなと思ってる ### 表示の体感速度は既存画面と同じぐらい? print $header; # 関数のリファレンスを渡す &DummyDAO::get_list2(\&view_row); print $footer; ------------------------------ ちゃんとテンプレートエンジンを使う場合は使えなさそうですが 今回はこれで良いかな…? と… ありがとうございました。