-PR-
解決済み

DBMとハッシュ

  • 困ってます
  • 質問No.73151
  • 閲覧数216
  • ありがとう数1
  • 気になる数0
  • 回答数2
  • コメント数0

お礼率 29% (20/68)

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

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

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

sub OKWeb {
$OKWeb{'123'} = 'あいう';
      ~
return $OKWeb{$_[0]};
}
としてみたりといった方法と比べても速いのでしょうか。
また上記の方法以外にもっと速くデータを参照できる方法がありましたら教えて下さい。
通報する
  • 回答数2
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.1
レベル10

ベストアンサー率 64% (73/113)

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

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

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

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

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

なお、SDBM_Fileなどはファイルサイズの制限があったりします。
perldoc AnyDBM_Fileなどをご覧ください。
お礼コメント
ryogoku

お礼率 29% (20/68)

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

その他の回答 (全1件)

  • 回答No.2
レベル10

ベストアンサー率 64% (73/113)

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

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

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

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

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

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


このQ&Aで解決しましたか?
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


専門家があなたの悩みに回答!

-PR-

ピックアップ

-PR-
ページ先頭へ