3

KiokuDB用来存储几个 Moose 对象和几个简单的数组结构(散列和数组)。

我不需要任何花哨的搜索、交易等,只需获取(lookup)对象的能力。此外,一旦我完成创建数据库,就可以将其设置为只读。永远不会对其进行任何更改。

我使用 KiokuDB 的主要(唯一?)原因是保留对象图。

占 DB 总大小的最大对象是 Moose 对象,其中有一个相对较大的数组(我们称之为对象large_obj)。以前,我使用 Storable +甚至 JSON +存储large_obj(单独)。它运行良好,我对结果非常满意(使用 gzip 将存储文件压缩到其原始大小的 5% 左右)。PerlIO::gzipPerlIO::gzip

还有另一个较小的 Moose 对象,它基本上是由 20-30k 个小型 Moose 对象组成的数组。

现在,在迁移到 KiokuDB 之后,我首先使用了简单的 Hash 后端,然后再次将其转储到文件中(使用 Cmd)PerlIO::gzip。这在相对较小的情况下效果很好large_obj,但是一旦它变大,我就会出现内存不足的错误。我猜哈希支持不适合大型对象。

然后我尝试了推荐的 Berkeley 后端,虽然它看起来有点过头了(如前所述,我并不真的需要所有花哨的数据库功能)。它的运行速度比原始的 Storable +PerlIO::gzip解决方案慢得多,占用的空间要多得多,而且对于更大的对象,它也会耗尽内存!(我使用 3GB RAM 的 ubuntu)。

我也尝试了Files backend,但它失败了:

Too many open files at /usr/local/perls/perl-5.12.2/lib/site_perl/5.12.2/Directory/Transactional.pm line 130.
    (in cleanup) Too many open files at /usr/local/perls/perl-5.12.2/lib/site_perl/5.12.2/Directory/Transactional.pm line 130.

您对如何以既节省空间又维护对象图的方式存储对象有什么建议吗?

4

1 回答 1

3

使用Data::Serializer实现您自己的后端:

package KiokuDB::Backend::Serialize::Data::Serializer;
use Moose;
use Moose::Role;

use Data::Serializer;

use namespace::clean -except => 'meta';

with qw(
    KiokuDB::Backend::Serialize
    KiokuDB::Backend::Role::UnicodeSafe
    KiokuDB::Backend::Role::BinarySafe
);

has '_serializer' => (
    is       => 'ro',
    isa      => 'Data::Serializer',
    required => 1,
    lazy     => 1,
    default  => sub {
        Data::Serializer->new(
            serializer => 'FreezeThaw', # Storable, FreezeThaw, Data::Denter, Config::General, YAML, PHP::Serialization, XML::Dumper, and Data::Dumper
            digester   => 'MD5', # See http://search.cpan.org/~gaas/Digest-1.16/Digest.pm#Digest_speed
            compress   => 1,
            compressor => 'Compress::Zlib', # Compress::Zlib or Compress::PPMd
        );
    },
);

sub serialize {
    my ( $self, $entry ) = @_;

    return $self->_serializer->serialize($entry);
}

sub deserialize {
    my ( $self, $blob ) = @_;

    return $self->_serializer->deserialize($blob);
}

sub serialize_to_stream {
    my ( $self, $fh, $entry ) = @_;

    $self->_serializer->store( $entry, $fh );
}

sub deserialize_from_stream {
    my ( $self, $fh ) = @_;

    $self->_serializer->retrieve($fh);
}

__PACKAGE__
于 2010-10-26T19:29:15.000 回答