2014-02-14 2 views
3

저는 약 1,700,000 개의 키가있는 해시를 만드는 Perl 프로젝트를 진행하고 있습니다. 이것은 너무 커서 메모리에 저장할 수 없습니다 (노트북의 메모리는 약 1 천만 개의 키만 보유 할 것입니다). 솔루션은 디스크에 데이터를 저장하는 것이지만 실제로 이것을 실행하는 데 문제가 있습니다. 여기에 내가 무엇을 시도했다입니다 :Perl : 디스크에 거대한 해시를 저장하는 데 문제가 있습니까?

DB_File

use strict; 
use DB_File; 
my $libfile = shift; 
my %library; 
tie %library, "DB_File", "$libfile"; 
for (my $a = 1; $a < 17000000; a++) { 
    # Some code to generate key and value # 
    $library{$key} = $value; 
} 

이 나에게 세그먼트 오류 제공 : 루프를 11 일부 길, 내가 이해하지 못하는 이유를.

버클리는

use strict; 
use BerkeleyDB; 
my $libfile = shift; 
my $library = new BerkeleyDB::Hash 
    -Filename => $libfile, 
    -Flags => DB_CREATE; 

for (my $a = 1; $a < 17000000; a++) { 
    # Some code to generate key and value # 
    $library->db_put($key, $value); 
} 

이 첫 번째 1500 만 키에 대해 잘 작동하는 것 같다, 그러나 아래로 크게 둔화 마침내 완전히 루프의 끝 부분에서 정지. 나는 이것이 기억 문제라고 생각하지 않는다. 루프를 네 조각으로 나누고 네 개의 개별 프로그램에 넣은 다음 순차적으로 실행하면 (처음에는 데이터베이스에 4 백만 개의 레코드가 추가됩니다) 처음 세 개는 성공적으로 완료되지만 데이터베이스가 약 15 개가 될 때 네 번째 핸들이 중단됩니다 백만 개의 열쇠. 그래서 아마도 BerkeleyDB 만 해시로 ~ 1500 만 건의 키를 처리 할 수있는 것처럼 보입니다. ???

DBM : 예비 시험에서

use strict; 
use DBM::Deep; 
my $libfile = shift; 
my $library = new DBM::Deep $libfile; 

for (my $a = 1; $a < 17000000; a++) { 
    # Some code to generate key and value # 
    $library->put($key => $value); 
} 

깊은이 확인을 작동하는 것 같다,하지만 정말 느린 : 천 키 당 약 5 초, 또는 ~ 22시간 전체 루프를 실행합니다. 나는 가능한 한 이것을 피하기를 원할 것이다.

이 패키지 중 하나의 문제 해결에 대한 제안이나 동일한 것을 달성하기위한 다른 옵션에 대한 아이디어에 대해 매우 감사드립니다.

UPDATE

+0

mongodb와 같은 nosql 데이터베이스를 사용하는 것이 가능한 옵션인지 확인하십시오. http://www.mongodb.com/learn/nosql – stevenl

+0

시도한 perl 및 모듈의 OS 및 버전은 무엇입니까? 평균 키와 평균값은 얼마나 큽니까? – ysth

+1

"키 정렬"모드에서 항목을 생성 할 수 있습니까? 해시에서 btree로 "key sorted"삽입으로 성능을 개선했을 때 거대한 BerkeleyDB의 한 사례를 기억합니다. 개선은 매우 중요하지만 충분하지 않습니다. – AnFi

답변

2

"키 정렬 모드"로 액세스 거대한 버클리의 성능을 향상시킬 수 있습니다 BTREE로 전환. 필요한 디스크 I/O 조작의 수를 줄입니다.

사례 연구 : 뉴스에보고 된 사례 중 하나에 : 나는 거대한 버클리 생성 시간을 기억 comp.mail.sendmail은 "키가 분류"와 BTREE 20 분 해시 몇 시간에서 감소되었다 추가합니다. 어쨌든 너무 길어서 SQL 데이터베이스에 액세스 할 수있는 소프트 기능으로 전환하여 BerkeleyDB에 SQL 데이터베이스 "덤프"가 필요하지 않도록 직접 결정했습니다. (virtusertable, sendmail-> postfix)

0

PostgreSQL을 사용해 볼 수 있습니다.

먼저 두 열의 키 값 테이블을 생성 VARCHAR 데이터베이스에 데이터를 복사 대학원 :: 대량 복사를 사용하는 대신 각각의 삽입, 다음

괜찮을 것이다.

한 번에 100MB를 넣지 않는 것이 좋습니다. COPY 명령이 실패하면 PostgreSQL은 디스크에 삽입 된 행을 계속 유지할 것이므로 VACUUM FULL이면 테이블을 제거합니다 . (한 번은 5GB를 많이 처리했고 두 개는 거의 끝나지 않는 몇 가지 제약 조건에서 실패하고 디스크는 롤백으로 돌아 가지 않습니다.)

PS : 당신이 직접 너무 DBD :: 대학원을 사용할 수 있습니다 https://metacpan.org/pod/DBD::Pg#COPY-support

모든 사본을 마무리 한 후에는 키에 인덱스를 만들고, 더 빠른 속도를 필요로하는 경우 레디 스를 사용하거나 MAXMEMORY 정책

로 memcached를 할 수 있습니다
관련 문제