我最近在一张表中进行了一些字符串搜索,其中有大约50k字符串,相当大,我会说但不是那么大。我正在为“搜索结果”之类的东西做一些嵌套查询。我正在使用LIKE语句来获取搜索关键字的匹配项。
我遇到了MySQL的全文搜索,我尝试过,因此我在str
列添加了全文索引。我知道全文搜索不适用于虚拟创建的表,甚至不适用于Views
,因此具有子选择的查询将不适合。我提到过我正在进行嵌套查询,例如:
SELECT s2.id, s2.str
FROM
(
SELECT s1.id, s1.str
FROM
(
SELECT id, str
FROM strings
WHERE str LIKE '%term%'
) AS s1
WHERE s1.str LIKE '%another_term%'
) AS s2
WHERE s2.str LIKE '%a_much_deeper_term%';
这实际上还没有应用于任何代码,我只是做了一些测试。此外,通过使用Sphinx(性能明智)可以很容易地实现这样的搜索字符串,但让我们考虑Sphinx不可用,我想知道它在纯SQL查询中如何运行良好。在没有添加全文的表上运行此查询大约需要2.97 secs
。 (取决于搜索词)。但是,在具有全文添加到str
列的表上运行此查询已完成,如104ms,这很快(我认为?)。
我的问题很简单,使用 LIKE 是否有效,或者在通常我们使用 MATCH <添加全文的表格中使用它是一个好习惯/ strong>和反对声明?
谢谢!
答案 0 :(得分:1)
在这种情况下,您不一定需要子选择。你可以使用:
SELECT id, str
FROM item_strings
WHERE str LIKE '%term%'
AND str LIKE '%another_term%'
AND str LIKE '%a_much_deeper_term%'
...但也提出了一个很好的问题:排除行的顺序。我猜MySQL很聪明,可以假设最长的术语是最具限制性的,所以从a_much_deeper_term
开始,它将消除大部分记录,然后仅在几行上执行附加比较。 - 与此相反,如果你从term
开始,你可能会得到许多可能的记录,然后你必须将它们与术语的st进行比较。
有趣的是,您可以使用原始子选择示例强制进行比较的顺序。这使得有机会根据更长的汉字来决定哪个术语是最具限制性的,但是例如:
...等。您还可以根据您正在处理的文本信息类型应用一些启发式。
修改强>
这只是一种预感,但可以将LIKE
应用于全文索引中的words
。然后将这些行与索引进行匹配,就好像你已经为完整单词进行了分类一样。
我不确定这是否真的已经完成,但是对MySQL人来说是一件很聪明的事情。另请注意,只有在全文搜索中实际存在所有可能的事件时才能使用此理论。为此你需要:
%id%
,那么它也可以是3个字母单词的一部分,默认情况下将其排除在FULLTEXT索引之外。