哪种搜索技术/方法是最快的?(在文件搜索的情境下)

8
我不知道普通Windows搜索使用了什么技术。但是有一种技术,你可以一次性对文件进行索引,然后稍后使用索引进行更快速的搜索。(例如:Windows搜索4.0)
除此之外,还有其他比这更快速的搜索方式吗?您能从实现的角度详细说明吗?(假设我需要实现它)
为了让人们更容易理解,让我以这种方式表述:
假设我想构建一个搜索应用程序,其搜索操作类似于我们在Windows中使用的搜索操作。
我的问题是,构建这样一个应用程序可能有哪些可行的选项/方法/方式? (哪些比现有的更快。)
(是否可以使用二叉搜索树这种技术?)

2
首先,你有必要自己构建吗?有很多好的开源项目,比如Lucene(和.NET的NLucene),其中包含了许多这方面的功能。除非你绝对必须从头开始构建,否则我会使用这个。即使你这样做,我也会从这样的项目源代码开始。实际上并没有一种最好的搜索技术。基于内容和搜索对象,有一整套技术可供选择。请提供更多细节信息。 - Anthony Gatlin
@安东尼 感谢你,安东尼。我知道有很多好的开源项目可用于实现搜索应用程序。但是你可以假设我想从头开始构建它,没有特定的原因。正如我之前问过的,我想知道是否可以使用二叉搜索树。我之所以这样说,是因为我很久以前在某个地方读到过它,但我忘记了概念。让我们看看是否有人能帮忙。 - Ravindra S
我认为你不会得到更好的答案,因为包括Windows Search 4.0、Google Desktop Search等在内的所有搜索技术都内部使用索引和B+树,这是目前市场上所有数据库中用于索引的主要方法。而且说实话,除了索引之外,没有更快的方法,索引的表现取决于你选择的算法。 - Akash Kava
8个回答

22

在大型语料库上进行全文搜索的基本技术有两种:posting lists和suffix arrays。

Posting lists是(term, document_id)对的列表,可以选择包含文档中的位置信息。如果按term排序或哈希,就可以创建一个高效可搜索的全文索引。

有多种技术可以使posting lists更小,访问更快,更新更快,更加灵活,但有可能会降低准确性。Lucene可能是当今最好的现成posting list文本索引器,与你之前的评论相反,它可以索引PDF、Microsoft Word等文件中的文本。由Thomas Maierhofer链接的Lucene.net项目看起来是一个相当不错的移植,不过你始终会落后于Java版本的最新进展。

对于远超内存大小的语料库,你必须把posting list存储在磁盘上。这就要求使用简单的二叉搜索树来访问它已经不可行了:如果你有十万个文档每个文档都有一万个单词,那么你有十亿个posting,这意味着你的二叉搜索树至少有30层。问题是从根到叶子的路径上的30个节点通常位于磁盘的不同部分,因此磁盘需要查找30次才能找到一个term的posting!这大约需要2.5秒,速度太慢了。

然而,有一种修改过的二叉树数据结构称为“B树”,可以使用。Lucene使用一个类似于B树的简单数据结构,但更容易支持大规模的更新。我在自己的dumbfts项目中编写了一个非常简单的版本,它实现了一个用几页Python编写的全文搜索引擎来搜索我的电子邮件。我每天都在使用它,它是免费软件,并且对我所用的目的来说运行得相当不错,但它并不像Lucene那样是一个世界级的搜索系统。

作为缩小Posting列表以换取精度的例子,《Managing Gigabytes》书(和mg4j项目)有一个名为“签名最小完美哈希表”的数据结构,它实际上并不存储被索引的术语,而只存储它们的哈希值。因此,存在误判的可能性 —— 您必须检索包含该术语的文档,以确认它们确实存在。

后缀数组是一种更紧凑但运行速度略慢的基数树(也称为trie)实现,GLIMPSE 和其他一些程序使用了这种数据结构,但如今它们基本上已经不再使用。 它们具有一些发布列表数据结构中不存在的灵活性 - 例如,它们允许正则表达式搜索和带有拼写错误的搜索,但它们并不像其他技术那样快速。 最近还进行了一些基于后缀数组的 Burrows-Wheeler 变换工作,提供了一种压缩算法,在这种算法中,压缩文件 就是 全文索引! 这种方法最好记录在名为FM 索引 的版本中,虽然我听说可能还有早期版本的技术未经发表。 不过,与上述其他技术不同,我认为当文档是 PDF 文件或类似格式时,该技术实际上并不起作用 - 您仍然可以使用相同的方法提取每个页面的文本版本并对其进行索引,但无法获得压缩原始文档的好处。
我熟人 Tim 在 2003 年写了一系列关于搜索的非常好的介绍性博客文章(Tim Bray 的“搜索系列”),至今仍然不错。它们更深入地涵盖了这些内容(除了最近的发展)。
Ravi:这是你在寻找的信息吗?
编辑:感谢 Martin 修复我的格式!

2
+1。看起来这个答案(或任何其他答案)对于OP来说还不够入门。我怀疑任何东西都不会。写得非常好。如果它没有帮助到OP,至少它教会了我。 - Lieven Keersmaekers
谢谢,Lieven!我认为原帖作者自从我发布以来就没有阅读过它——他在这里或他的问题上都没有留下评论。 - Kragen Javier Sitaker
我并不是想抱怨,只是想说我们没有任何关于这是否“足够你”的信息,因为你之前的评论并不是针对这个答案的。 - Kragen Javier Sitaker

14

看看 Lucene。它是一个用于文本(文件)的超快速搜索库。还有可用的Lucene.NET。如果你喜欢自己实现,它是一个很好的起点和基准。


谢谢Thomas的回复。但是Lucene似乎只适用于文本文件,而不适用于其他类型的文件。 - Ravindra S
2
@Ravi:解决方案是从PDF、DOC等文件中提取文本,然后将提取的文本馈送给Lucene。 - Stephen C
确切地说,《Lucene实战》一书专门有一整个章节介绍此内容。 - João Silva
将Lucene.NET与Microsoft IFilters连接起来非常容易 - 您可以使用IFilter接口获取文本,然后将其添加到Lucene索引中 - http://en.wikipedia.org/wiki/IFilter - Dan Diplo
你在真实应用中尝试过吗?也许可以在 GitHub 上找到完整的源代码实现(使用良好的模式和实践)。 - Kiquenet

2
你是在寻找文件名还是想查看内容?你希望用什么语言实现这个功能?
如果你只需要查找文件名,那么索引可以大大提高性能。但如果你需要打开每个文件来查找,索引只有在您打开可能包含所需内容的文件时才会有所帮助。
但无论如何,你仍需要打开每个文件直到找到你要找的内容为止。

是的。我想看到内容。谈到实现部分,.NET框架是首选。 - Ravindra S
那么你就需要遍历文件,逐个打开并在内容中进行搜索...一种方法是为您的索引添加标签。标签告诉当前文件属于哪些最重要的分类...这样您就可以有效地以适当的速度找到文件了。问候。 - Atmocreations

1
全文搜索:想象一下你有一个单词字典,对于每个单词,你都写下了包含该单词的文档和该单词在文档中的确切位置。这被称为全文索引,它让你可以执行布尔搜索并匹配精确短语。全文索引可以轻松扩展到数百万个文档,并且这通常是Windows搜索4.0所使用的方法。还请参见Lucene或Sphinx。
概念搜索:概念搜索允许您输入一堆相关单词(甚至是整个文档),并返回最接近您输入的文件。基于您的文档集合,它生成可以推断单词之间语义联系的概念空间。 这使得它能够返回更相关的搜索结果,因为计算机“理解”您正在搜索的概念,将匹配概念上相似的单词和短语。这通常是企业搜索和电子发现解决方案所使用的方法。 提供概念搜索的产品包括Engenium和Autonomy。
元搜索:与直接搜索内容不同,您可以搜索有关内容的信息,称为元数据。元数据可以包括标签、关键字、作者名称、时间戳等内容。例如,如果您知道文档编写的大致日期,您可以在搜索条件中包含该元数据,以更快地缩小搜索结果的范围。

正如你所知,有许多方法可以处理搜索,每种方法都涉及许多不同类型的数据结构。如果你想让我详细阐述某个特定领域,我可以为你做到。


1

网络上有很多关于全文搜索的研究论文,也有很多源代码。如果你看一下它们,你会发现在现代硬件上使用二叉搜索树不会提供好的结果。二叉搜索树是一种非常特定的数据结构,在具有多级缓存的现代cpu上并不尽可能快。快速的数据结构比2更高的扇出。

此外,这个问题更适合使用(基数)trie。请参见维基百科。


1

你可以使用Knuth-Morris-Pratt或Boyer-Moore搜索算法,它们非常快速,而且不需要索引。


3
它们的时间复杂度与你的语料库大小成线性关系。比如,如果你有一个15GB的语料库,你的磁盘每秒可以读取40MB,那么你至少需要六分钟才能获得搜索结果,假设你的CPU足够快以跟上磁盘的速度。相比之下,我每天查询一个15GB的全文索引,并在几秒钟内获得结果。Google拥有数十亿个网页的全文索引,可以在不到一秒钟内为您提供搜索结果。 - Kragen Javier Sitaker

1

没有单一的技术或“万能药”。但如果你从头开始,最好理解一下thisthis关于这个主题的标准文本。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接