【问题标题】:MySQL: Best way to do a backwords full text search?MySQL:进行向后全文搜索的最佳方法?
【发布时间】:2012-02-26 18:35:38
【问题描述】:

我正在尝试进行基本的反向完整测试搜索,但不知道最好的方法。

基本上,我有一个关键短语表,如下所示:
id - 短语
1 - “你好世界”
2 - “再见世界”
3 - “这是我的世界”

然后我有一个设置字符串,例如“欢迎来到 hello world 组”。我想在我的表中找到与短语完全匹配的所有行的 ID。意思是“o the”将不匹配,因为这个词是“to the”。 “hello”也不匹配,因为世界是“hello”。

使用全文搜索,这可以通过搜索以下内容轻松实现:
反对 ('"hello world"' 在布尔模式);

问题是,我不相信我可以使用全文搜索,因为全文搜索会找到包含单个短语的所有行。我想要与单个集合匹配的所有短语(来自一组已知的短语)。

我知道如何使用 RegEx 使用以下方法来执行此操作,但是这会变慢。在有 400,000 个关键短语的表格上,它花费了 40 多秒:

WHERE “我知道我想搜索的数据放在这里” REGEXP CONCAT('[[:<:>phrases, '[[:>:]]')

我需要的是一种更优化的方式来做到这一点。即使我必须暂时将其添加到表中而不实际单独检查每个关键字,我如何才能将其作为全文搜索进行。

我非常感谢您的反馈,因为这确实导致我的网站在添加新数据方面滞后。

【问题讨论】:

  • 致任何有类似问题的人:尽管我最终测试了一个理论。我所做的是在我的关键字表中添加一列并将其设置为关键字,按单词分割,然后加入 |,确保它以 | 开头和结尾。所以“hello my world”变成了“|hello|my|world|”。从那里,当一个新的字符串进来时,我做了同样的事情,所以“让我们测试你好我的世界”变成了“|lets|test|hello|my|world|”。有了这个,我可以很容易地找到我的世界,因为它有开始和结束|确保“shello my world”不匹配。
  • 这将包含约 400,000 个关键短语的 50 秒查询缩短到约 1.2 秒。仍然很慢,但足以让我的应用程序继续运行。为了更好地优化这一点,我最终可能会按照 Jogo 的建议进行搜索层,但这对于现在来说已经足够了,因为这会导致所有停机时间

标签: mysql full-text-search where-clause


【解决方案1】:

如果您愿意考虑从数据库中读取短语并构建用于优化短语检测的单独数据结构的解决方案,则有两种主要技术可以解决该问题。哪一个最适合您取决于多种因素,特别是:

  1. 短语列表的更新频率
  2. 在运行短语检测之前是否以及如何标记文本
  3. 目标字符串有多长

选项 1:短语的哈希表 这意味着您只需将每个短语作为键插入哈希表(又名 dictionaryhash map 在许多编程语言中)。短语 id 成为值。更新既快速又容易,但检测给定字符串中的短语可能很困难:首先,您需要对字符串进行标记,并确保短语只出现在标记边界之间。其次,您不仅需要在散列中查找每个标记,还需要查找连续标记的每一对、三重、四重等。如果目标字符串通常很短,这仍然很有效。您还可以在磁盘上维护哈希表的副本,例如使用伯克利数据库。大多数编程语言的标准库中都有现成的模块。

选项 2:搜索树(或者,稍微高级一点,最小化搜索树或有限状态机)。这可以以非常节省空间的方式实现,但通常比哈希表大(尽管 400k 条目根本不会成为问题)。短语检测期间的一大优势是在进行查找之前无需删除标记(或标记边界之间的候选短语)。相反,您在文本中的每个候选起始位置执行最长匹配查找。存储在磁盘上是可能的,尽管在大多数编程语言中不会有用于此的标准库模块。在 trie 中更新非常容易,但在最小化的 trie 或 FST 中可能会变得困难(并且可能很耗时)。

两个选项都允许在磁盘上维护数据结构(或将其副本存储在磁盘上,而实际查找发生在内存中)。但是你不会获得交易安全或容错(我知道你不是在寻找)。

【讨论】:

  • Jogo:感谢您的反馈。在我出城的前一天晚上我正在处理这个问题,所以还没有完成它。最后大家都赶上了,所以今晚晚些时候再看看你的选择。给您投票以寻求帮助,如果有任何一项工作,我会将其标记为已接受。再次感谢!
  • 我最终使用了一个效率较低但更简单的解决方案,以便我可以轻松地将其全部保存在 mySQL 中。我最终可能会尝试以上两种基准测试,因为即使我的也是“慢”,但现在我可以肯定地使用它,所以我不必完全从我的数据库中取出逻辑。感谢您的帮助!
【解决方案2】:

您可以使用搜索引擎。例如索尔。您可以针对文本设置特定的搜索过滤器。 + 仅搜索单词。 + 它会非常快。

或者,第二个想法,您可以创建自己的表来存储所有单词和短语 ID。并仅搜索该表的匹配词。它会更快,因为您可以更好地为单词添加索引,而不是完全添加短语。

【讨论】:

  • 问题不在于全文搜索的速度。 FTS 非常快。问题是我想找到与字符串匹配的关键短语,而不是与关键短语匹配的字符串。全文搜索基本上与我正在做的完全相反,搜索引擎也是如此。明白我的意思吗?
  • 对不起,现在你完全失去了我。你有短语表和一些文本。并且您想查找文本中的所有短语 ID。对吗?
  • 没错。做一个搜索引擎似乎我无法做到这一点。我只能找到包含某个短语的所有文本。
  • 嗯..我现在只是在这里提出想法。也许可以使用某种 sql 查询来返回搜索文本中的所有短语 id。 SELECT DISTINCT(p.id) FROM phrases AS p INNER JOIN text_table AS t ON t.text LIKE '%' + p.phrase + '%' AND t.id = X 你不知道这个查询速度。跨度>
  • 很可能与 like is "hello world" 将匹配它不应该匹配的 "ello world"。我使用 RegEx 的原因,虽然它非常慢。抱歉延迟回复,写完就出城了,忘记了。感谢您的意见
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2015-04-30
  • 2011-11-04
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
相关资源
最近更新 更多