2012-02-22 5 views
4

私は、次のような約100万行ありますPerlで非常に高速に検索:ハッシュ値を再ロードすることは可能ですか?

A : value of A 
B : value of B 
| 
| 
| 
Z : value of Z upto 100 million unique entries 

現在、私は私のプログラムを実行するたびに、私はいくつかの時間がかかるハッシュとしてファイル全体をロードします。実行時に私は一度ハッシュを作成し、バイナリデータ構造やインデックスファイルとして保存することができます場合、私は疑問に思って

などA、Bを知っている与えられたA、Bの値にアクセスする必要があります。最低限のプログラミングで可能なことは何であろうか。

ありがとうございます! -Abhi

+0

'perlの-e '1..100_000_000ため++ $ hを{$ _}は、''私のために7秒かかります。それは実際にはかなり速いです。私はあなたのメモリが使い果たされているので、あなたのコードが遅いかもしれないと思うので、仮想メモリの使用に頼っています。最適なソリューションはおそらく、データセット全体をメモリにロードする必要がないソリューション(データベースソリューションなど)です。 – ikegami

+0

あなたは右にStorableモジュールを使用している間、私は、メモリの制限を打っています考え出しています。生産データセットには500行あります。私はDBベースのソリューションに行く必要があると思う。 – Abhi

答えて

7

Storableを見てください - それはあなたがやりたいこと、使用が非常に簡単である必要があります:あなたのプログラムは、実際にはもちろん、CPUの速度によって制限されている場合

use Storable; 
store \%table, 'file'; 
$hashref = retrieve('file'); 

にのみ役立ちます。データ構造は非常にシンプルなので、ディスクから読み取るよりも速く解析することができます。この場合、Storableはあなたを大いに助けません。

+1

これはコアモジュールであり、Perlに付属しています。 – rjh

+0

涼しいおかげで..私は私くぼみがここに含まれるいくつかの構文解析のオーバーヘッドを持っています。保存可能は素晴らしいです – Abhi

+0

そして、それはいつどのように保存されますか? 100,000,000エントリのハッシュは、 'perl'とかStorableがそれを作成するかどうかを作るのに同じ時間を要します。 – ikegami

9

私は、ディスク上のキー/値データベースを示唆しています。 Perlのtie functionのために、彼らは通常、メモリ内のハッシュと同一に使用することができます。あなたのハッシュが非常に大きい場合、Perlのハッシュよりも読み込み/書き込みの方が速く、ディスクへの保存/読み込みを自動的にサポートします。

BerkeleyDBは古いのお気に入りです:データベースへ

use BerkeleyDB; 
# Make %db an on-disk database stored in database.dbm. Create file if needed 
tie my %db, 'BerkeleyDB::Hash', -Filename => "database.dbm", -Flags => DB_CREATE 
    or die "Couldn't tie database: $BerkeleyDB::Error"; 

$db{foo} = 1;   # get value 
print $db{foo}, "\n"; # set value 
for my $key (keys %db) { 
    print "$key -> $db{$key}\n"; # iterate values 
} 

%db =(); # wipe 

変更は自動的にディスクに保存され、スクリプトの複数の呼び出しを通じて持続します。

オプションについてはperldocをチェックしますが、最も重要なのは、次のとおりです。

# Increase memory allocation for database (increases performance), e.g. 640 MB 
tie my %db, 'BerkeleyDB::Hash', -Filename => $filename, -CacheSize => 640*1024*1024; 

# Open database in readonly mode 
tie my %db, 'BerkeleyDB::Hash', -Filename => $filename, -Flags => DB_RDONLY; 

これは結局Perlのである(より複雑ですが、はるかに高速データベースライブラリがTokyo Cabinetだろう、と他の多くのオプションがもちろんあります。 ..)

+0

ありがとう..私はこれを念頭に置いておきます – Abhi

+0

私はメモリのためにDBベースの方法を使用しなければならないと思います。私は、BerkeleyDBのをENVを初期化しようとしていたが、このスクリプトは私にエラーを与えている:コードここに=新しいBerkeleyDBの '$ berkeleyDB_env :: Envの \t \t \t \t \t \t -Cachesize => $ cacheSizeの :いないオープンな環境そのようなファイルやディレクトリをすることができます\t \t \t \t \t \tまたは "環境変数$ BerkeleyDB :: Error \ n"を開くことができません。 'なぜコードがフォーマットされていないのか分かりません...ごめんなさい。 – Abhi

+0

@ rjh:BerkeleyDBにハッシュリファレンスを結び付けることもできます。私は私のデータ構造にもっと夢中になりたいです。 $ a - > {$ b} - > {$ c} - > {$ d} = eのようになりますか?私は 'BerkeleyDB :: Btreeを使用していますが、エラーが発生しました'パッケージ "BerkeleyDB :: Btree"を介してオブジェクトメソッド "TIESCALAR"を見つけることができません。 – Abhi

1

私はTie::Fileをコアに含めておき、データ構造全体をメモリに読み込まず、必要に応じてディスクから必要に応じてアクセスすることをお勧めします。

+1

正しいアイデア(メモリにすべてをロードしない)、間違った実装(Tie :: File)。 Tie :: Fileでレコードを検索すると、線形時間がかかりますが、ハッシュは一定時間にレコードを検索するために使用されます。 (-1の値を取り消すには+1) – ikegami

関連する問題