3

SQLite データベースと Perl モジュールを使用して問題に取り組もうとしています。最終的には、何千万ものエントリをログに記録する必要があります。各アイテムの唯一の一意の識別子は、URL のテキスト文字列です。私はこれを2つの方法で行うことを考えています:

方法 #1: 良いテーブル、悪いテーブル、並べ替えられていないテーブルを用意します。(html をチェックして、それが必要かどうかを判断する必要があります。) 合計 10 億ページ、各テーブルに 3 億 3,300 万の URL があるとします。追加する新しい URL があり、それがいずれかのテーブルにあるかどうかを確認して確認し、一意である場合は Unsorted に追加する必要があります。また、このオプションを使用すると、多くの行を移動できます。

方法 2: Master と Good の 2 つのテーブルがあります。Master には 10 億のページ URL がすべてあり、Good には私が必要とする 3 億 3300 万の URL があります。新しい URL は、同じことを行う必要があります。ただし、今回は 1 つのテーブルのみを照会し、Master から行を削除することはなく、データを Good に追加するだけです。

したがって、基本的には、巨大な SQLite データベースをすばやくクエリして、20 文字までのテキスト文字列が一意かどうかを確認し、そうでない場合は追加するための最適なセットアップを知る必要があります。

編集: Perl モジュールを使用して Berkeley DB を動作させようとしていますが、ダイスはありません。ここに私が持っているものがあります:

use BerkeleyDB;

$dbFolder = 'C:\somedirectory';
my $env = BerkeleyDB::Env->new ( -Home => $dbFolder );

my $db  = BerkeleyDB::Hash->new (
-Filename => "fred.db", 
-Env => $env );
my $status = $db->db_put("apple", "red");

そして、これを実行すると、次のようになります。

Can't call method "db_put" on an undefined value at C:\Directory\perlfile.pl line 42, <STDIN> line 1.
4

3 に答える 3

5

あなたがやりたいことをするために、SQLiteの代わりにハッシュを使用する傾向があります。ハッシュは、ソートされた順序で値を保持したり、データの冗長コピーをインデックスに保持したりする必要なく、存在をテストするように最適化されています。データに適用されたハッシュ アルゴリズムは、データが存在する場合に格納される場所を生成します。その場所を探して、そこにあるかどうかを確認できます。ハッシュテーブルをRAMに保持する必要はないと思います。

ハイブリッド ハッシュ/SQLite アプローチを採用する方法を次に示します。

SQLite テーブルを作成する

STORE
id INTEGER PRIMARY KEY
BUCKET (integer, indexed) 
URL (text, not indexed)
status 

これらのテーブルを STORE1、STORE2、および STORE3 の 3 つをステータス別に保持する場合は、これらのテーブルを持つことができます。

各ストアに 250,000,001 個の個別のバケットがあると仮定しましょう。(この数を試すことができます。素数にしてください)。

URL 文字列と 250,000,0001 の 2 つの入力を取り、1 ~ 250,000,001 の数値を返すハッシュ アルゴリズムを見つけます。

URL を取得したら、それをハッシュ アルゴリズムにフィードすると、検索対象の BUCKET が通知されます。

Select * from STORE where BUCKET = {ハッシュ関数によって返される値}。

BUCKET フィールドのインデックスはすぐに行を返し、URL を調べることができます。現在の URL がそれらのいずれでもない場合は、追加します。

INSERT STORE(BUCKET, URL) VALUES( {your hash return value}, theURL). 

SQLite は整数値のインデックスを作成しますが、これは URL のインデックス作成よりも効率的だと思います。また、URL は一度だけ保存されます。

于 2010-09-27T19:44:51.797 に答える
2

これが最適かどうかはわかりませんが、「良い」テーブルが URL 列に一意の制約を持つように SQLite DB を設定できます。おそらく、Perl で比較を行うのに十分な RAM がありません (素朴な解決策は、URL がキーであるハッシュを作成することですが、10 億のページがある場合、非常に多くのメモリが必要になります)。

挿入を行うときが来ると、データベースは一意性を強制し、重複した URL を挿入しようとすると何らかのエラーをスローします。DBI が異なるエラー メッセージに対して異なるエラー値を返す限り、このエラーをキャッチして無視することができます。

于 2010-09-27T19:43:23.343 に答える
2

が定義されていない場合$dbは、データベースを開くことができません。その理由を調べる必要が$!あります。$BerkeleyDB::Error

データベースはもう作成しましたか?そうでない場合は、 が必要-Flags => DB_CREATEです。

作業例:

use strict;
use warnings;
use BerkeleyDB;

my $dbFolder = '/home/ysth/bdbtmp/';

my $db  = BerkeleyDB::Hash->new (
    -Filename => "$dbFolder/fred.db", 
    -Flags => DB_CREATE,
) or die "couldn't create: $!, $BerkeleyDB::Error.\n";

my $status = $db->db_put("apple", "red");

しかし、私は BerkeleyDB::Env に有用なことをさせることができませんでした。何を試しても、コンストラクターは undef を返しました。

于 2010-09-28T05:42:29.560 に答える