2015-02-24 52 views
0

为了简化我的问题,可以说我有一张有很多书籍和各自内容的表格。另一方面,我有一个关键字表。我想找到匹配的对。请看下面的简单Perl脚本,它很好地说明了这个问题。如何匹配两个数据库表中的相关值?

#title => content 
%books = (
    "Foodworld" => "Cheesburgers and Hamburgers are the best you can ...", 
    "Marvelous Salad" => "Russian dressing is superb when ...", 
    "Delicious Steaks" => "Only BBQ RipEye" 
); 

#id => keyword 
%keywords = (
    "1234" => "Cheeseburgers", 
    "2345" => "dressing", 
    "9789" => "Hamburgers" 
); 

while (my ($title,$content) = each %books) { 
    while (my ($keywordID, $keyword) = each %keywords) { 
    if ($content =~ /$keyword/) { 
     print "$title \t $keywordID \n"; 
    } 
    } 
} 

输出将是:

Marvelous Salad 2345 
Foodworld  1234 
Foodworld  9789 

我的问题是,藏书包含〜70000个标题和关键词〜30,000字的列表。两者都在MySQL服务器上的单独表中。有什么建议么?你将如何解决这个任务?你能指点我一个好的方向吗?

+0

我认为你是在正确的轨道上。这个“预先计算好的指数”的最终目标是什么? “图书”和“关键字”表的更改频率如何? – mwp 2015-02-24 21:16:04

+0

你是说你的'books'表只有'title'和'book'作为列,而''keywords'表有'id'和'keyword'?这听起来像有人只做了一半的数据库设计。 'books'表集会还需要一个'id'列,以保存标题字符串的索引,并且需要一个包含'book_title'和'keyword_id'作为外键的联结表'keywords_by_book',并且定义关键字出现在每本书中。该表需要一段时间才能生成,但一旦完成,查找速度将比纯Perl中可以写入的任何时间都快。 – Borodin 2015-02-24 22:46:16

+0

不,当然有一个'books.id'和一些更多的列,但这会让我的问题更加复杂 – 2015-02-26 15:08:49

回答

0

算法上,我看不到任何快捷方式 - 你必须检查每个关键字的每个标题,因此你得到的两个循环是唯一的方法来做到这一点。

我提供的一种加速过程的方式是可以编译正则表达式 - 而且值得做一下你的场景。

Perl通常编译一个静态正则表达式,但如果它包含一个变量,它不能。你可以,但是,使用:

Is there a way to precompile a regex in Perl?

which'll有所改善的事情。您可能发现类似:

my $regex = join ("|", keys %keywords); 
$regex = qr/$regex/; 

可能更有效率,使3万字编译RE,而不是单独测试每个。你需要自己测试才能检查。 (Devel::NYTProf可能有帮助)

我也建议 - 它看起来像你的代码的方式,一本书的完整内容加载到$content。您希望避免一次只能使用一个 - 这看起来就像您。但是我建议你需要谨慎对待从你的数据库中获取所有图书的大量数据 - 一次取一个,然后检查它,假设$content相当大。

我想补充 - 这个问题可以很好地扩展,因为你没有数据依赖。你可以在Perl中使用线程或分叉来并行化。但要小心,因为DBI不是线程安全的。 (或至少不一定)

+0

算法上现在有了解决方法,那很不幸。你是否也会在数据库之外做到这一点。 (比如,例如perl脚本)或者可能存储的MySQL过程更快? – 2015-02-24 22:16:51

+0

很难说。仅仅因为在处理之前必须提取内容,“从源头上”可能会更有效率。但如果您可以将处理器成本从数据库服务器中移出,可能会进行折衷。特别是因为这是一个很好的并行问题。 – Sobrique 2015-02-24 22:39:50

2

初看起来,这听起来像你想创建一个junction table书籍与key_words。实际上,您可能想要创建两个联结表---一个联系标题与key_words,另一个联系内容联系key_words。

联结表简单由成对的列组成,每个列都包含“REFERENCES FOREIGN KEY”...其中一个用于“book”ID,另一个用于“key_word”ID。

您仍然需要执行嵌套循环来创建这些连接键引用,并且该表可能很大(key_word和title /内容的每个组合都是一行)。但查询可能相当快。

通过这些连接表中的任何一个,您大概会有三种类型的简单查询。一个发现所有包含给定key_word的书籍,另一个发现所有与给定书籍关联的key_words,最后一个会告诉你是否存在给定的key_word/book组合。 (其他更复杂的查询可以找到像交叉点和设置书籍和key_words的区别的东西---所有包含“dolphin(s)”和“pet(s)”的书籍)。适用于词干,你可能想用库来标准化单词到词干)。

连接表通常在其两列上都有一个复合键(并且通常没有自己的代理键)。这隐含地创建了一个索引,同时对该组合强加了UNIQUE约束。 “REFERENCES FOREIGN KEY”条款还确保了关联的参照完整性---并且意味着您必须在之前创建书/标题和key_word条目您可以创建任何关联。 (进一步删除这些实体将需要删除所有联结条目或使用DDL上的CASCADE选项)。

相关问题