158

我刚刚阅读了一篇在 SQL 中提到“全文搜索”的帖子。

我只是想知道 FTS 和 LIKE 之间的区别是什么。我确实阅读了几篇文章,但找不到任何可以很好地解释它的东西。

4

6 回答 6

193

一般来说,“精度”和“召回”之间存在权衡。高精度意味着呈现的不相关结果更少(没有误报),而高召回率意味着丢失的相关结果更少(没有误报)。使用 LIKE 运算符可为您提供 100% 的精确度,并且不会对召回做出任何让步。全文搜索工具为您提供了很大的灵活性来调整精度以获得更好的召回率。

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

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

全文搜索的其他典型特征是

  • 词法分析或标记化——将非结构化文本块分解为单个单词、短语和特殊标记
  • 形态分析或词干提取——将给定单词的变体折叠成一个索引词;例如,将“mice”和“mouse”,或“electrification”和“electric”视为同一个词
  • 排名——测量匹配记录与查询字符串的相似度
于 2008-10-22T07:08:04.183 回答
42

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

于 2008-10-22T07:04:44.983 回答
30

MySQL 从启用的全文搜索列的单词创建一个索引,并在该索引上执行搜索。MySQL 使用复杂的算法来确定与搜索查询匹配的行。

另外,从这个 SO 答案

全文搜索有几个优点。

索引:

就像是:

WHERE Foo LIKE '%Bar';

无法利用索引。它必须查看每一行,看看它是否匹配。但是,全文索引可以。事实上,全文索引可以在匹配单词的顺序、这些单词之间的距离等方面提供更多的灵活性。

词干:

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

加权结果:

全文索引可以包含多个列。例如,您可以搜索“桃派”,索引可以包括标题、关键字和正文。与标题匹配的结果可以被赋予更高的权重,因为更相关,并且可以排序以显示在顶部附近。

缺点:

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

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

于 2016-03-03T07:04:29.313 回答
18

Like 只使用通配符,并没有那么强大。

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

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

于 2008-10-22T07:05:11.770 回答
12

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

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. 单词/术语的长度

例如,可以触发此 SQL 以提取与给定单词 XYZ 匹配的所有行:

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

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

然而,LIKE 对此一无所知。它被迫线性扫描句子/字符串并找到所有匹配的术语。添加通配符会增加混乱。正如您可以想象的那样,它适用于小长度的字符串,但对于较长的句子会失败。当有一段或一整页的文字等时,绝对没有可比性。

于 2015-04-01T05:04:35.393 回答
3

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

于 2012-02-09T15:13:22.100 回答