【问题标题】:How does a full text search server like Sphinx work?像 Sphinx 这样的全文搜索服务器如何工作?
【发布时间】:2012-04-24 09:34:57
【问题描述】:

谁能用简单的话解释一下像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)

是否可以用简单的语言解释这些查询是如何工作的以及它们是如何生成的?

【问题讨论】:

    标签: sql full-text-search search-engine sphinx thinking-sphinx


    【解决方案1】:

    倒排索引是您问题的答案:http://en.wikipedia.org/wiki/Inverted_index

    现在,当您通过 sphinx 运行 sql 查询时,它会从数据库中获取数据并构造倒排索引,这在 Sphinx 中就像一个哈希表,其中键是使用 crc32(word) 计算的 32 位整数和value 是包含该单词的 documentID 列表。

    这使它超级快。

    现在您可以争辩说,即使是数据库也可以创建类似的结构来使搜索变得超快。然而,最大的不同是 Sphinx/Lucene/Solr 索引就像一个单表数据库,不支持任何关系查询 (JOIN) [来自 MySQL 性能博客]。请记住,索引通常仅用于支持搜索,而不是数据的主要来源。因此,您的数据库可能处于“第三范式”,但索引将完全被反规范化,并且主要包含需要搜索的数据。

    另一个可能的原因是数据库通常存在内部碎片,它们需要对巨大的请求执行过多的半随机 I/O 任务。

    这意味着,例如,考虑到数据库的索引架构,查询会导致索引,而索引又会导致数据。如果要恢复的数据分布广泛,结果将需要很长时间,这似乎是数据库中发生的情况。

    编辑:还请查看 cpp 文件中的源代码,如 searchd.cpp 等以了解真正的内部实现,我想你只是看到了 PHP 包装器。

    【讨论】:

    • 你说它在你运行查询时构造索引?这似乎是开始构建索引的一个相当晚的时间点。你指的是哪个词并不明显。这一点都不是很清楚。然后,您指出 Sphinx 仅存储“搜索所需的信息”。我们已经知道了。这说明不了什么。
    • 否 - indexer 运行“sql_query”以从数据库中获取数据,以构建倒排索引。当你运行 search 查询(到searchd)时,结果是从索引中的数据编译而来的(不查询数据库)
    【解决方案2】:

    您正在查看的那些查询是 sphinx 使用的查询,用于从数据库中提取数据副本并放入自己的索引中。

    Sphinx 需要一份数据副本来构建它的索引(其他答案已经提到该索引的工作原理)。然后,您从 searchd 守护程序请求结果(匹配特定查询) - 它会查询索引并返回匹配的文档。

    您选择的特定示例看起来相当复杂,因为它只提取了一部分数据,可能是为了分片 - 出于性能原因将索引分成几部分。并且正在使用范围查询——因此可以零碎地访问大数据集。

    可以使用更简单的查询来构建索引,例如

    sql_query = select id,name,description from items
    

    这将创建一个 sphinx 索引,其中包含两个字段 - namedescription,可以搜索/查询。

    搜索时,您会得到唯一的idhttp://sphinxsearch.com/info/faq/#row-storage

    【讨论】:

      【解决方案3】:

      全文搜索通常使用倒排索引的一种实现。简而言之,它在标记(单词)中制动索引字段的内容并保存对该行的引用,由每个标记索引。例如,第 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
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-20
          • 2012-04-06
          相关资源
          最近更新 更多