2012-04-06 2 views
2

크기가 12GB가 넘는 Berkeley DB 파일에서 데이터를 읽고 키 값 쌍으로 텍스트 파일에 쓰려고합니다. 그러나 2 천 6 백만 건의 레코드를 읽은 후 프로세스가 중단되므로이 작업을 수행 할 수 없습니다. perl/ruby를 사용하여 파일을 읽으려고했으나 레코드를 가져 오는 객체가 2600 만 개의 레코드를 저장할 수있는 것 같습니다. BDB 파일을 분할 한 다음 레코드를 읽을 수있는 방법이 있습니까? 또는 청크로 데이터를 읽고 처리하는 방법을 찾았습니까?큰 Berkeley DB 파일에서 데이터를 읽을 수 없습니다.

+1

코드를 보여 주면 누군가가 문제를 해결할 수 있도록 도와 줄 수 있습니다. –

답변

0

코드가 보이지 않는 경우는 거의 없습니다. BerkeleyDB 모듈을 사용하고 있습니까? 파일이 해시 테이블 형식입니까? Perl과 Java로 질문을 태그했습니다. 근래에 Perl과 Ruby뿐만 아니라 Java를 사용하여 파일을 읽으려고 했습니까?

해시 및 스칼라 값에 대한 지원 데이터가 C와 같은 간단한 문자열과 비교할 때 엄청나기 때문에 Perl을 사용하여 가상 메모리 제한에 도달했을 수 있습니다.

내가 거기 버클리 DB 파일을 분할하는 방법이 있지만, 요구 사항은 간단하고 당신이 그것으로 도움이 필요한 경우 펄 코드를 제시해주십시오 C.

의 몇 줄

에 기록 될 수 있는지 의심 , 또는 C 또는 Java로 다시 작성하십시오. 데이터가 텍스트 파일에 키/값 쌍으로 저장되면 Perl은 쉽게 처리 할 수 ​​있습니다.


편집

나는 당신이 DB_File 모듈이 제공하는 기본 버클리 DB API를 사용하는 것이 좋습니다. 이렇게하면 모든 데이터를 단일 Perl 해시에 보관하지 않아서 문제를 해결할 수 있습니다.

이 코드는 DB 파일에 액세스 할 수 없으므로 컴파일되지만 최소한의 데이터에서만 테스트됩니다. DB_File를 사용하는 그 방법은 다음 같은 문제가있는 경우

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 모듈을 시도하는 것이 좋습니다. 같은 저자에 의해 작성되었지만 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 $!; 
+0

java를 사용하여 어떻게 동일한 작업을 수행 할 수 있는지 알고 계십니까? – vikknp

+0

Berkely DB 용 Java 라이브러리에 익숙하지 않지만 Perl DB_File 모듈에서 제공하는 네이티브 API를 사용하여 문제를 해결할 수 있다고 생각합니다. 나는 내 대답을 설명하기 위해 추가했습니다. – Borodin

+0

이것은 도움이되지 않습니다. 다시 3 개의 파일 2를 만들었습니다. 2 개의 파일에는 1 천만 개의 레코드가 있고 마지막으로 6 백만 개의 레코드가 있습니다. 따라서 여전히 데이터를 단일 해시로 유지하는 것으로 보입니다. My $ db = tie my % dbhash, 'DB_File', 'TestId', O_RDONLY, 0644, $ DB_BTREE 또는 die " 'TestId'파일을 열 수 없습니다 : $! \ n"; – vikknp

관련 문제