2014-02-14 59 views
3

我的工作,其中包括建立一個哈希以約1,700萬鍵一個Perl項目。這太大了無法存儲在內存中(我的筆記本電腦的內存只能容納大約1000萬個按鍵)。我知道解決的辦法是將數據存儲在磁盤上,但我有在實踐中執行這個麻煩。以下是我已經試過:的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部分,對於原因,我不明白。

的BerkeleyDB

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); 
} 

這似乎很好的工作,對前15個百萬個密鑰,但隨後大幅下降減緩並最終完全凍結附近的循環結束。我不認爲這是一個記憶問題;如果我將循環分成四部分,將它們放在四個獨立的程序中,然後按順序運行(每次向數據庫添加約400萬條記錄),前三個成功完成,但第四個在數據庫大約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和你試過的模塊?你的平均密鑰和平均值有多大? – ysth

+1

您能否在「按鍵排序」模式下生成條目?我認爲我記得一個巨大的BerkeleyDB的情況下,從哈希切換到btree與「鍵排序」插入提高性能。改進非常顯着,但還不夠。 – AnFi

回答

2

切換到B樹可以改善在「關鍵排序模式」訪問巨大的BerkeleyDB性能。它減少了所需的磁盤I/O操作數量。

案例研究: 在一種情況下,在新聞報道:comp.mail.sendmail我記得巨大的BerkeleyDB創作時間從幾個小時縮短爲哈希到20分鐘以「鍵排序」 B樹追加。這是太長反正這樣的傢伙決定轉向軟能夠直接訪問SQL數據庫SQL數據庫「堆」的BerkeleyDB避免需求。 (的virtusertable,sendmail->後綴)

0

你可以試試PostgreSQL的。

首先創建一個表有兩個列,鍵和值,VARCHAR將被罰款,

然後,而不是插入每一個,使用PG :: BulkCopy將數據複製到數據庫中。

我建議一次插入不超過100MB,因爲當你的COPY命令失敗時,PostgreSQL將保留插入磁盤之前的那些行,並且它只會在VACUUM FULL表中刪除。 (有一次我處理很多5GB的一對夫婦的失敗,它的一些約束幾乎結束和磁盤再也沒有回到上回滾..)

PS:你可以使用DBD :: PG直接過:https://metacpan.org/pod/DBD::Pg#COPY-support

全部複製完成後,就可以在關鍵創建一個索引,如果你需要更快的速度,使用Redis的或MAXMEMORY政策

的memcached