我刚刚读到一篇文章提到 SQL 中的“全文搜索”。

我只是想知道 FTS 和 LIKE 之间有什么区别。我确实读过几篇文章,但找不到任何可以很好解释的内容。

有帮助吗?

解决方案

一般来说,“精确度”和“召回率”之间存在权衡。高精度意味着呈现的不相关结果较少(无误报),而高召回率意味着缺失的相关结果较少(无误报)。使用 LIKE 运算符可为您提供 100% 的精确度,并且不会影响召回率。全文搜索工具为您提供了很大的灵活性,可以降低精度以更好地回忆。

大多数全文搜索实现都使用“倒排索引”。这是一个索引,其中键是单个术语,关联值是包含该术语的记录集。全文搜索经过优化以计算交集、并集等。这些记录集,通常提供排名算法来量化给定记录与搜索关键字的匹配程度。

SQL LIKE 运算符的效率可能极低。如果将其应用于未索引的列,则将使用完整扫描来查找匹配项(就像对未索引字段的任何查询一样)。如果列已建立索引,则可以针对索引键执行匹配,但效率远低于大多数索引查找。在最坏的情况下,LIKE 模式将具有前导通配符,需要检查每个索引键。相比之下,许多信息检索系统可以通过在选定字段中预编译后缀树来支持前导通配符。

全文搜索的其他典型功能包括

  • 词汇分析或令牌化 - 将一大堆非结构化的文本分解为单个单词,短语和特殊令牌
  • 形态学分析或茎 - 给定单词分为一个索引项的汇总变体;例如,将“小鼠”和“鼠标”或“电气化”和“电动”视为相同的单词
  • 排名 - 衡量匹配记录与查询字符串的相似性

其他提示

FTS涉及索引文本字段中的单个单词,以便快速搜索许多记录。使用LIKE仍然需要您在字段中进行字符串搜索(线性或类似)。

MySQL根据启用的全文搜索列的字词创建索引,并对此索引执行搜索。 MySQL使用复杂的算法来确定与搜索查询匹配的行。

此外,从此SO答案

  

全文搜索有一些优势。

     

<强>索引:

     

类似的东西:

WHERE Foo LIKE '%Bar';
     

无法利用索引。它必须查看每一行,看它是否匹配。但是,全文索引可以。实际上,全文索引可以在匹配单词的顺序,这些单词的接近程度等方面提供更大的灵活性等。

     

<强>词干:

     

全文搜索可以阻止单词。如果您搜索运行,则可以获得“运行”的结果。或“跑步”。大多数全文引擎都有各种语言的词典。

     

加权结果:

     

全文索引可以包含多个列。例如,您可以搜索“桃子馅饼”,索引可以包含标题,关键字和正文。与标题匹配的结果可以加权更高,更相关,并且可以排序以显示在顶部附近。

     

<强>缺点:

     

全文索引可能很大,比标准B-TREE索引大很多倍。出于这个原因,许多提供数据库实例的托管提供商禁用此功能,或至少为此收取额外费用。例如,我上次检查过,Windows Azure不支持全文查询。

     

全文索引的更新速度也可能较慢。如果数据变化很大,则与标准索引相比可能会有一些滞后更新索引。

仅使用通配符,并不是那么强大。

全文允许更复杂的搜索,包括And,Or,Not,甚至类似的声音效果(SOUNDEX)和更多项目。

我将开始查看SQL CONTAINS()FREETEXT()和相关的全文搜索项,以帮助更好地了解可用的内容。

真正的区别在于扫描方法。对于全文搜索,单词(术语)用作散列键 - 每个键都与键(术语)出现的文档数组相关联。如下所示:

Document sets = {d1, d2, d3, d4, ... dn}
Term sets = {t1, t2, t3, .. tn}

现在,术语 - 文档矩阵(哪个文档的术语成员)可以表示为:

t1 -> {d1, d5, d9,.. dn}
t2 -> {d11, d50, d2,.. dn}
t3 -> {d23, d67, d34,.. dn}
:
tn -> {d90, d87, d57,.. dn}

当请求进入时,要求“获取包含单词/术语t1的所有文档” - 然后返回文件集 {d1,d5,d9,.. dn }。

你可以破解一个非规范化的表模式来存储文档 - MySQL表中的每一行都将被视为“文档”。并且TEXT列可以包含段落等。反向索引将包含作为散列键的术语和作为文档ID的行-id。

请记住,此SQL查询将具有或多或少的O(1)性能。查询将独立于

  1. TEXT列中的字数/术语数
  2. 符合条件的行/文档数
  3. 单词/术语的长度
  4. 例如,可以触发此SQL以提取与给定单词XYZ匹配的所有行:

    SELECT * 
    FROM   my_table 
    WHERE  MATCH (my_text_column) against ('XYZ' IN boolean mode) ;
    

    警告:如果向此查询添加ORDER BY,则运行时将根据几个参数而变化,其中一个参数是匹配的行/文档的数量。所以要小心。

    然而,LIKE却一无所获。它被迫线性扫描句子/字符串并找到所有匹配的术语。添加外卡增加了混乱。它可以很好地适用于小长度弦乐,你可以想象,但是对于较长的句子来说,它会失败。当有段落或整页文本等时,绝对没有可比性。

FTS更高效,更强大(特别是对于断字符和词干功能)  ...但请检查您的要求,因为有时DB不支持所有语言,例如MSSQL不支持希腊语(请查看此页 http://msdn.microsoft.com/en-us/library/ms176076(v = sql.110).aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top