2

我正在尝试从大小 > 12 GB 的 Berkeley DB 文件中读取数据,并以键值对的形式写入文本文件。但我不能这样做,因为我的进程在读取 2600 万条记录后停止。我尝试使用 perl/ruby 读取文件,但获取记录的对象似乎只能容纳 2600 万条记录。有什么方法可以拆分 BDB 文件然后读取记录吗?或者如果我能找到一些方法来读取数据块然后处理它们?

4

1 回答 1

0

没有看到你的代码,没什么好说的。你在使用BerkeleyDB模块吗?文件是哈希表的形式吗?你已经用 Perl 和 Java 标记了你的问题;您是否尝试过使用 Java 以及 Perl 和 Ruby 读取文件?

您可能已经使用 Perl 达到了虚拟内存限制,因为与 C 等中的简单字符串相比,散列和标量值的支持数据是巨大的。

我怀疑是否有拆分 Berkely DB 文件的方法,但要求很简单,只需几行 C 即可编写。

如果您需要帮助,请出示您的 Perl 代码,或者用 C 或 Java 重写它。一旦数据作为键/值对存储在文本文件中,Perl 就可以轻松处理它。


编辑

我建议你使用DB_File模块提供的原生 Berkely DB API。这将避免将所有数据保存在单个 Perl 哈希中,并且可能会解决您的问题。

此代码可以编译,但仅在最少数据上进行测试,因为我显然无法访问您的数据库文件。

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

如果这种使用方法DB_File有同样的问题,那么我建议您尝试使用BerkeleyDB模块。它是由同一作者编写的,但它的接口似乎与 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 回答