2

サイズが 12 GB を超える Berkeley DB ファイルからデータを読み取り、キーと値のペアでテキスト ファイルに書き込もうとしています。しかし、2,600 万件のレコードを読み取った後にプロセスが停止するため、そうすることができません。perl/ruby を使ってファイルを読み込んでみましたが、レコードを取得するオブジェクトはちょうど 2600 万レコードを保持できるようです。BDB ファイルを分割してレコードを読み取る方法はありますか? または、データをチャンクで読み取って処理する方法を見つけることができたら?

4

1 に答える 1

0

コードを見ずに言うことはほとんどありません。BerkeleyDBモジュールを使用していますか? ファイルはハッシュ テーブル形式ですか。Perl と Java の両方で質問にタグを付けました。Java だけでなく、Perl や Ruby を使用してファイルを読み取ってみましたか?

C などの単純な文字列と比較して、ハッシュとスカラー値のサポート データが膨大であるため、Perl を使用して仮想メモリの制限に達した可能性があります。

Berkely DB ファイルを分割する方法があるかどうかは疑問ですが、要件は単純で、C の数行だけで記述できます。

ヘルプが必要な場合は、Perl コードを表示するか、C または Java で書き直してください。データがキーと値のペアとしてテキスト ファイルに保存されると、Perl で簡単に処理できます。


編集

モジュールが提供するネイティブの Berkely DB API を使用することをお勧めしDB_Fileます。これにより、すべてのデータが単一の Perl ハッシュに保持されることが回避され、問題が解決される可能性があります。

このコードはコンパイルされますが、明らかに DB ファイルにアクセスできないため、最小限のデータでのみテストされます。

use strict;
use warnings;

use DB_File;

my $db = tie my %dbhash, 'DB_File', 'TestId', O_RDONLY, 0644, $DB_BTREE
    or die "Cannot open file 'TestId' :$!\n";

my $file = 0;
my $fh;
my $c = 0;

my ($key, $val);

my $stat = $db->seq($key, $val, R_FIRST);
while ($stat == 0) {

  if (not $fh or $c == 10_000_000) {
    $file++;
    open $fh, '>', "TestId$file.txt" or die $!;
    $c = 0;
  }

  print $fh "$key|$val\n";
  $c++;
}
continue {
  $stat = $db->seq($key, $val, R_NEXT);
}
close $fh or die $!;

undef $db;
untie %dbhash;

編集 2

そのアプローチで同じ問題が発生する場合は、代わりにBerkeleyDBモジュールDB_Fileを試すことをお勧めします。これは同じ作者によって書かれていますが、Perl のハッシュとは独立しているように見えるインターフェースを持っています。

これは、代替モジュールを使用した以前の試みと同等のコードです。最小限のデータセットで問題なく動作します。これでもうまくいかない場合は、モジュールの作者である Paul Marquess に連絡することをお勧めします。

use strict;
use warnings;

use BerkeleyDB;

my $db = BerkeleyDB::Btree->new(-Filename => 'TestId')
    or die "Cannot open file 'TestId' :$!\n";

my $cursor = $db->db_cursor;

my $file = 0;
my $fh;
my $c = 0;

my $key = my $val = "";

my $stat = $cursor->c_get($key, $val, DB_FIRST);
while ($stat == 0) {

  if (not $fh or $c == 10_000_000) {
    $file++;
    open $fh, '>', "TestId$file.txt" or die $!;
    $c = 0;
  }

  print $fh "$key|$val\n";
  $c++;
}
continue {
  $stat = $cursor->c_get($key, $val, DB_NEXT);
}

close $fh or die $!;
于 2012-04-07T00:11:17.447 に答える