プロが教えるわが家の防犯対策術!

参考書を読んだ所、dbmデータベースは
データの検索・削除等を行う場合に速くて良いとありました。

ここで質問なのですが、データベースのデータを変更せず
データの参照のみを必要とする場合、

外部ファイル化して同じ効果を得られる別の方法…
例えば、ハッシュ配列をそのままdb.txtに保存して
require 'db.txt';
としてみたり、

sub OKWeb {
$OKWeb{'123'} = 'あいう';
      ~
return $OKWeb{$_[0]};
}
としてみたりといった方法と比べても速いのでしょうか。
また上記の方法以外にもっと速くデータを参照できる方法がありましたら教えて下さい。

A 回答 (2件)

データのサイズや参照の仕方によるのではないでしょうか。


比較的小さなデータから1レコード取り出すようなときは、
大抵の場合ハッシュでも充分かと思います。場合によっては
*DBM_Fileよりも高速でしょう。

ただ、ハッシュの式を外部ファイルにしろサブルーチンにしろ
埋め込んでおいて読ませる場合、Perlがその文を解釈、評価する
時間が掛かることにご注意ください。つまりあまりデータがでかいと、
いつまでたってもそのファイルをがらがら読んでて終わらないよ、
ということもあり得るわけです。もちろんすべてを読みこむのに
必要なメモリも消費しますね。

読みこんだあと全部ソートしたいとか集計したいとかの
目的があるならメモリに読みこむ必要があるでしょうが、
たくさん読みこんだ挙句に参照するデータはひとつ二つだけ…といった
ことになるのだったら、*DBM_Fileなどを利用して外部ファイルに置いて
おいて、必要な部分だけ読みに行く方が有効でしょう。

他に、検索がより複雑になるのだったらRDBMSなどにお任せしたほうが
楽でしょうし、逆にデータが必ず順番に並んでいてサイズも固定長
にしておけば読みこむべき場所が「データ番号 * データサイズ」で一発
でseekできるから速い、なんてテクニックが使える状況もあるでしょう。
あるいはひとつひとつ検索するのを10回繰り返すより、
ひとつ検索したあとはそこから続けて10レコード分まとめて
読みこんじゃえばいい、というような構造のファイルを作れるとか。
(まあ実際、*DBM_Fileの中には上記のようなテクニックを使っている
ものもあると思います。多くの人が改良し合ったコードの方が効率が
良いでしょうから、もし自前のものを書くおつもりならその前にいろいろと
調査されることをお薦めします)

というわけで、速いかどうかは、データの構造ややることによる、と
お答えします。月並みで申しわけありません。

なお、SDBM_Fileなどはファイルサイズの制限があったりします。
perldoc AnyDBM_Fileなどをご覧ください。
    • good
    • 0
この回答へのお礼

詳しく、丁寧なご回答ありがとうございました。
疑問が解決しました!
本当はポイントを全部つけたかったのですが
同一人物へのポイントは駄目なんですね。すいません。
ありがとうございました。

お礼日時:2001/05/09 09:51

おわかりのことでしょうが老婆心ながら補足します。


ハッシュは優れたデータ格納方法ですが、作成時には各キーの
ハッシュ値を計算して、対応するバケットにデータを突っ込んでおく、
またPerlの場合要素数がある程度増えると自動的にバケットの数を
増やす仕組みになってますけど、そういったもろもろの処理の時間が、
わずかながらでも掛かっていることにご注意ください。

DBファイルの場合その作成時にこれらの処理をまとめて行っておく
(インデックスを張るような場合)と考えると、数百件のデータを
頻繁に呼び出すようなときはやっぱりDBを使うか、データ形式に
特化した格納方法を使う方が有利です。

また、例としてお書きになったサブルーチンを使うほうは、呼び出すたびに
毎回代入し、ハッシュ作成を行うので、データが少ない間ならばいいですが多くなる
ほどとても遅くなるでしょう(一度しかそのサブルーチンを呼ばない
ならまた話は別です)。

あと、「全部ソートしたいとか集計したいとかの目的があるなら
メモリに読みこむ必要がある」と書きましたが、集計する場合は
1レコード読んでは集計して、そのレコードを廃棄して次のレコード
を読みこめばいいですね。メモリの節約にもなります。

[蛇足]
よく初心者の方のプログラムで見かけるのが
my @data = <DATA>;
でファイルを丸ごと読んでしまう方法ですが、これはファイル
が小さいうちはいいでしょうけど、大きくなるとその分メモリを
消費するわけですから、あまり望ましいとはいえません。
(カウンタのCGIサンプルから来てるのかな?なぜみな一様にこんな
書き方をするのか不思議です)
while (<DATA>) {
}
で1行ずつ処理すべきです。多少早ければメモリなんか…という
気持ちもわかりますが、あまりメモリ消費量が多くなればOSが
メモリのスワップアウトでがらがらとディスクの読み書きを始め、
全体が極端に重くなるでしょう。メモリ消費も少ないのに越したことは
ありません。

本題からはずれてしまいました。すいません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!