3

我试图通过使用 SQLite 数据库和 Perl 模块来解决问题。最后,我需要记录数千万条记录。每个项目的唯一唯一标识符是 URL 的文本字符串。我正在考虑以两种方式做到这一点:

方式#1:有一张好桌子,坏桌子,未排序的桌子。(我需要检查 html 并决定是否需要它。)假设我们总共有 10 亿个页面,每个表中有 3.33 亿个 URL。我有一个要添加的新 URL,我需要检查它是否在任何表中,如果它是唯一的,则将其添加到 Unsorted。另外,我会用这个选项移动很多行。

方式 #2:我有 2 张桌子,Master 和 Good。Master 拥有全部 10 亿个页面 URL,Good 拥有我想要的 3.33 亿个。新的 URL,需要做同样的事情,除了这次我只查询一个表,我永远不会从 Master 中删除一行,只会将数据添加到 Good。

所以基本上,我需要知道快速查询一个巨大的 SQLite 数据库的最佳设置,以查看大约 20 个字符的文本字符串是否是唯一的,如果不是,则添加。

编辑:我现在正试图让 Berkeley DB 使用 Perl 模块工作,但没有骰子。这是我所拥有的:

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。

假设每个商店中有 250,000,001 个不同的存储桶。(你可以试验这个数字;使它成为质数)。

找到一个哈希算法,它接受两个输入,即 URL 字符串和 250,000,0001,并返回一个介于 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

我不知道这是否是最佳的,但您可以设置您的 SQLite DB,以便“好”表对 URL 列具有唯一约束。您可能没有足够的 RAM 在 Perl 中进行比较(天真的解决方案是创建一个以 URL 为键的哈希,但如果您有十亿页,您将需要大量内存)。

当需要进行插入时,数据库将强制执行唯一性,并在尝试插入重复的 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 回答