像Sphinx这样的全文搜索服务器是如何工作的?

19

有没有人能简单地解释一下全文搜索服务器(如Sphinx)的工作原理?在普通的SQL中,我们可以使用类似以下的SQL查询来搜索文本中的某些关键字:

select * from items where name like '%keyword%';

但是在各种Sphinx插件生成的配置文件中,我根本看不到任何类似这样的查询。它们包含类似以下SQL语句的语句,这些语句似乎将搜索划分为不同的ID组:

SELECT (items.id * 5 + 1) AS id, ... 
       WHERE items.id >= $start AND items.id <= $end 
       GROUP BY items.id
..
SELECT * FROM items WHERE items.id = (($id - 1) / 5)

能否用简单的话解释一下这些查询是如何工作和生成的?

4个回答

18
倒排索引是你问题的答案:http://en.wikipedia.org/wiki/Inverted_index 当你通过Sphinx运行SQL查询时,它从数据库中获取数据并构建倒排索引,在Sphinx中,它类似于哈希表,其中键是使用crc32(word)计算的32位整数,值是具有该单词的文档ID列表。
这使得查询变得超级快速。
现在你可以争论说即使数据库也可以创建类似的结构以使搜索变得超级快速。然而最大的区别在于Sphinx/Lucene/Solr索引类似于一个单表数据库,没有任何关系查询(JOIN)的支持[来自MySQL性能博客]。请记住索引通常只用于支持搜索,而不是作为数据的主要来源。因此,您的数据库可能处于“第三范式”,但索引将完全非规范化,并且包含大多数仅需搜索的数据。
另一个可能的原因是通常数据库内部存在碎片化,需要在大量请求上执行过多的半随机I/O任务。
这意味着,例如,考虑数据库的索引架构,查询会导致索引,进而导致数据的检索。如果要检索的数据分布广泛,则结果会花费很长时间,这似乎就是在数据库中发生的情况。
编辑:还请查看cpp文件中的源代码,如searchd.cpp等真实的内部实现,我认为你只是看到了PHP包装器。

你说运行查询时会构建索引?这似乎是一个相当晚的时间点来开始构建索引。而且不清楚你指的是哪个单词。这一点并不是非常清晰。然后你强调Sphinx仅存储“搜索所需的信息”。我们已经知道了这一点。这并没有解释任何问题。 - Gherman
不,'indexer' 会运行 'sql_query' 来从数据库中获取数据,以建立倒排索引。当你运行 'searchd' 的 搜索 查询时,结果是从索引中的数据编译而来的(不会查询数据库)。 - barryhunter

4
你所看到的查询是sphinx使用的查询,用于从数据库中提取数据的副本并将其放入自己的索引中。
Sphinx需要数据的副本来构建其索引(其他答案已经提到了索引的工作原理)。然后您可以向searchd守护程序请求结果(匹配特定查询)-它会查询索引并返回匹配的文档。
你选择的特定示例看起来相当复杂,因为它只提取数据的一部分,可能是为了分片-将索引分成几个部分以提高性能。并且正在使用范围查询-因此可以逐步访问大型数据集。
可以使用更简单的查询构建索引,例如:
sql_query = select id,name,description from items

创建一个sphinx索引,包含两个字段——namedescription,可供搜索/查询。

搜索时,您将返回唯一的idhttp://sphinxsearch.com/info/faq/#row-storage


1

全文搜索通常使用倒排索引的一种实现。简单来说,它将索引字段的内容分解为标记(单词),并保存对该行的引用,由每个标记进行索引。例如,对于第1行的The yellow dog和第2行的The brown fox,将生成如下所示的索引:

brown  -> row#2
dog    -> row#1
fox    -> row#2
The    -> row#1
The    -> row#2
yellow -> row#1

0
简短回答这个问题是,像MySQL这样的数据库是专门设计用于存储和索引记录并支持SQL子句(SELECT,PROJECT,JOIN等)的。尽管它们可以用于执行关键字搜索查询,但无法提供最佳性能和功能。像Sphinx这样的搜索引擎是专门为关键字搜索查询而设计的,因此可以提供更好的支持。

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