【问题标题】:Unable to read data from a large Berkeley DB file无法从大型 Berkeley DB 文件中读取数据
【发布时间】:2012-04-20 08:02:18
【问题描述】:

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

【问题讨论】:

  • 如果您显示您的代码,也许有人可以帮助您修复它。

标签: java perl berkeley-db


【解决方案1】:

没有看到您的代码就没什么好说的了。你在使用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 $!;

【讨论】:

  • 你知道我如何使用 java 做同样的事情吗?
  • 我不熟悉 Berkely DB 的 Java 库,但我相信使用 Perl DB_File 模块提供的本机 API 可以解决您的问题。我已添加到我的答案中以进行演示。
  • 这没有帮助。它再次创建了 3 个文件 2 有 1000 万条记录,最后有 600 万条记录。因此,它似乎仍然将数据保存在单个哈希中。我的 $db = tie my %dbhash, 'DB_File', 'TestId', O_RDONLY, 0644, $DB_BTREE or die "Cannot open file 'TestId' :$!\n";
  • 我只能建议您尝试使用 BerkeleyDB 模块的等效代码。我在我的答案中添加了第二个编辑。
  • 尝试在我的 64 位 Windows 7 机器上安装 BerkeleyDB 模块。但是得到编辑中提到的错误。不知道这将如何解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多