哪种搜索技术/方法最快? (在文件搜索的上下文中)

Posted

技术标签:

【中文标题】哪种搜索技术/方法最快? (在文件搜索的上下文中)【英文标题】:Which is the fastest search technique/method? (In context of file searching) 【发布时间】:2010-11-27 18:08:26 【问题描述】:

我不知道它们在普通的 Windows 搜索中使用什么。但是有一种技术,您可以一次使用文件索引,然后稍后使用索引来进行更快的搜索。(例如 Windows 搜索 4.0)

还有比这更快的搜索方法吗?您能从实施的角度详细说明吗? (假设我可能需要实现它)

为了便于理解,我这样说:

假设我想构建一个搜索应用程序,它执行类似于我们在 Windows 中使用的搜索操作。

我的问题是,构建这样的应用程序有哪些可能的选项/方式/方法? (并且比现有的更快。)

(可以使用二叉搜索树这种技术吗?)

【问题讨论】:

首先,您是否有理由必须自己构建?有很多优秀的开源项目,比如 Lucene(和用于 .NET 的 NLucene),它们内置了很多这样的功能。除非你绝对必须从头开始构建,否则我会使用这个。即使你这样做,我也会从这样的项目的源代码开始。实际上不只有一种最佳搜索技术。根据内容和您的搜索内容,有一整包。请向我们提供更多详细信息。 @Anthony 谢谢Anthony。我知道有很好的开源项目可用于实现搜索应用程序。但是你可以假设我想从头开始构建它。没有具体原因。正如我之前问过的,我想知道,使用二叉搜索树有用吗?我这么说是因为我很久以前在某个地方读到过它,但我忘记了这个概念。让我们看看是否有人帮忙。 我认为您不会得到更好的答案,因为包括 Windows Search 4.0、Google 桌面搜索等在内的所有搜索技术在内部都使用索引并使用 B+ 树,并且主要用于在当前存在的所有数据库中进行索引在市场上。老实说,除了索引之外,没有更快的方法,索引的性能取决于您选择的算法。 【参考方案1】:

您是只搜索文件名还是同时查看内容?你想用什么语言来实现这个?

如果您只查找文件名,那么索引会大大提高性能,而如果您需要打开要查找的每个文件,则索引仅有助于您仅打开这些文件您要查找的内容可能在哪里。

它仍然需要您打开每个文件,直到找到您要注意的内容。

【讨论】:

是的。我也想看看内容。说到实现部分,首选.net框架。 那么您必须遍历文件,打开每个文件并浏览内容...一种方法是将标签添加到索引中。标签告诉当前文件所属的最重要的类别......这就是您可以以适当的速度有效地找到文件的方式。问候【参考方案2】:

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

【讨论】:

感谢 Thomas。但 Lucene 似乎只适用于文本文件,而不适用于其他文件。 @Ravi:解决方案是从 PDF、DOC 等文件中提取文本并将提取的文本提供给 lucene。 没错,Lucene in Action 一书中有一整节专门介绍了这一点。 很容易将 Lucene.NET 与 Microsoft IFilters 挂钩 - 您使用 IFilter 接口获取文本,然后将其添加到 Lucene 索引 - en.wikipedia.org/wiki/IFilter 你在实际应用中试过了吗?可能是 github 中的完整源代码真实应用程序? (使用良好的模式和实践【参考方案3】:

全文搜索:假设您有一个单词词典,对于每个单词,您记下哪个文档包含该单词以及该单词在该文档中的确切位置。这称为全文索引,它允许您执行布尔搜索和匹配精确短语等操作。全文索引可以轻松扩展到数百万个文档,并且是 Windows Search 4.0 通常使用的。另请参阅 Lucene 或 Sphinx。

概念搜索:概念搜索允许您输入一堆相关的词(甚至是整个文档)并返回与您的输入最相似的文档。根据您的文档集合,它生成概念空间,允许它推断单词之间的语义链接。这允许它返回更相关的搜索结果,因为计算机“理解”您正在搜索的概念并将匹配概念上相似的单词和短语。这是企业搜索和电子发现解决方案通常使用的。提供概念搜索的产品包括 Engenium 和 Autonomy。

元搜索:您不是直接搜索内容,而是搜索有关内容的信息,称为元数据。元数据可以包括标签、关键字、作者姓名、时间戳等。例如,如果您知道编写文档的大致日期,您可以在搜索条件中包含该元数据,以更快地缩小搜索范围结果。

如您所知,有很多方法可以处理搜索,每种方法都涉及许多不同类型的数据结构。如果您希望我详细说明某个特定领域,我可以为您完成。

【讨论】:

【参考方案4】:

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

另外,这个问题更适合(基数)trie。请参阅***。

【讨论】:

【参考方案5】:

基本上有两种技术用于对大型语料库进行全文搜索:发布列表和后缀数组。

发布列表是 (term, document_id) 对的列表,可以选择在文档中包含一个位置。如果您按术语对其进行排序或散列,您将拥有一个可高效搜索的全文索引。

有多种技术可以使发布列表更小、访问速度更快、更新速度更快、更灵活,其中一些是以准确性为代价的。 Lucene 可能是当今最好的基于发布列表的现成文本索引器,并且(与您之前的评论相反)它可以索引 PDF、Microsoft Word 等文件中的文本。 Thomas Maierhofer 链接的Lucene.net project 看起来是一个相当合理的端口,尽管您当然总是落后于 Java 版本的前沿。

对于比内存大得多的语料库,您几乎必须将发布列表存储在磁盘上。这不利于使用简单的二叉搜索树来访问它:如果您有十万个文档,每个文档有一万个单词,那么您就有十亿个帖子,这意味着您的二叉搜索树的最小深度为 30。这样做的问题是从树根到叶子的路径上的 30 个节点通常位于磁盘的不同部分——因此磁盘必须搜索 30 次才能找到一个学期的帖子!这大约是 2.5 秒,速度太慢了。

然而,有一个被称为“B-tree”的二叉树数据结构的修改版本可以工作。 Lucene 使用了一种简单的数据结构,它很像 B 树,但更容易支持大规模更新。我在自己的dumbfts project 中编写了一个非常简单的相同数据结构版本,它在几页 Python 中为我的电子邮件实现了全文搜索引擎。我每天都在使用它,它是免费软件,并且非常适合我的用途,但它不像 Lucene 那样完全是世界级的搜索系统。

作为以准确性为代价缩小发布列表的示例,Managing Gigabytes 一书(和mg4j project)有一个称为“有符号最小完美哈希表”的数据结构,它实际上并不存储术语被索引的——只是它们的哈希值。因此,误报的可能性很小 - 您必须检索据称包含该术语的文档才能确认它们确实包含。

后缀数组是基数树(又名尝试)的更紧凑且速度稍慢的版本,由 GLIMPSE 和其他一些程序实现,但这些天它们基本上已经不再使用了。它们具有一些在发布列表数据结构中不存在的灵活性——例如,它们允许正则表达式搜索和拼写错误搜索,但它们并没有那么快。 Burrows-Wheeler Transform 最近有一些工作,它基于后缀数组,提供一种压缩算法,其中压缩文件全文索引!记录最好的版本称为FM-index,尽管我听说有该技术的旧版本,可能尚未发布。不过,与上面描述的其他技术不同,我认为当文档是 PDF 文件或类似文件时,这实际上不起作用——你仍然可以使用相同的方法来提取每个页面的文本版本并对其进行索引,但是你不需要'没有得到压缩原始文档的好处。

我的熟人蒂姆早在 2003 年就写了一篇非常好的介绍性系列博文on search,仍然非常棒。他们更深入地介绍了这些东西(最近的发展除外)。

Ravi:这是您正在寻找的信息吗?

编辑:感谢您修复我的格式,Martin!

【讨论】:

+1。似乎这(或任何其他答案)不足以让 OP 开始。我怀疑会发生什么。写得很好。如果它对 OP 没有帮助,至少它教会了我。 谢谢,利文!我认为 OP 自从我发布它以来就没有阅读它 - 他没有在这里或他的问题上发表评论。 我的意思不是听起来像是在抱怨——我只是说我们没有任何关于它是否“对你来说足够”的信息,因为你早期的 cmets 不是回应这个答案。【参考方案6】:

也许您可以根据自己的需要调整PigeonRank™ :)

【讨论】:

【参考方案7】:

您可以使用 knuth-morris-pratt 或 boyer-more 搜索,速度非常快,而且您不需要索引。

【讨论】:

它们在你的语料库大小上是线性时间的。如果您有一个 15GiB 的语料库,并且您的磁盘每秒可以读取 40MB,那么您至少需要 6 分钟才能获得搜索结果,前提是您的 CPU 速度足以跟上磁盘的速度。相比之下,我每天在 15GB 的语料库上查询全文索引,并在几秒钟内得到结果。 Google 拥有数十亿网页的全文索引,可以在不到一秒的时间内为您提供搜索结果。【参考方案8】:

没有单一的技术或“灵丹妙药”。但是,如果您确实从头开始,则最好了解有关该主题的 this 和 this 标准文本。

【讨论】:

以上是关于哪种搜索技术/方法最快? (在文件搜索的上下文中)的主要内容,如果未能解决你的问题,请参考以下文章

for 循环的 5 种写法,哪种最快?

for 循环的 5 种写法,哪种最快?

在字符串集合中搜索的最快方法

搜索字谜的最快方法是啥?

在python中搜索列表的最快方法

Java中最快的子字符串搜索方法是啥