mysql match() against() 或 match() against() 慢
mysql match() agains() OR match() against() SLOW
我 table 有很多行 (~2M)。
当我搜索它时喜欢
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some' '+word' IN BOOLEAN MODE)
它像魅力一样工作,在不到 0.5 秒内找到我需要的东西。
但是当我像这样搜索 2 组单词时
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some' '-word' IN BOOLEAN MODE)
OR
MATCH(name) AGAINST('+something' '-other' IN BOOLEAN MODE)
搜索有时需要超过一分钟。
我预计它会慢 2 倍(搜索 2 次),也许会慢一些(您仍然需要比较结果并删除重复项,但如果结果很少,应该不会花很长时间),但是不会再长了。添加 OR 后它的工作速度比 LIKE "%...%" OR LIKE "%...%"
谁能告诉我我做错了什么?
不幸的是,全文索引 have some limitations,无法正确合并两个独立全文搜索的结果就是其中之一:
The Index Merge optimization algorithm has the following known limitations:
- [...]
- Index Merge is not applicable to full-text indexes.
幸运的是,全文搜索可能更复杂,因此您可以自己合并搜索。您的第二个查询可以写成单个搜索,使用:
SELECT * FROM product WHERE
MATCH(name) AGAINST('(+something -other) (+some -word)' IN BOOLEAN MODE)
这定义了两个搜索集,如果两个 (...)
中的任何一个匹配都可以 - 这是一个 or
.
或者,您可以使用 union
而不是 or
,这允许 MySQL 实际上 运行 两个独立的全文搜索,然后合并两个结果,这基本上就是您的想法:
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some -word' IN BOOLEAN MODE)
UNION
SELECT * FROM product WHERE
MATCH(name) AGAINST('+something -other' IN BOOLEAN MODE)
这也适用于更复杂的情况,例如合并对不同列的搜索,但如果您想做 or
.
之外的其他事情,将不会那么容易
我 table 有很多行 (~2M)。 当我搜索它时喜欢
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some' '+word' IN BOOLEAN MODE)
它像魅力一样工作,在不到 0.5 秒内找到我需要的东西。
但是当我像这样搜索 2 组单词时
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some' '-word' IN BOOLEAN MODE)
OR
MATCH(name) AGAINST('+something' '-other' IN BOOLEAN MODE)
搜索有时需要超过一分钟。
我预计它会慢 2 倍(搜索 2 次),也许会慢一些(您仍然需要比较结果并删除重复项,但如果结果很少,应该不会花很长时间),但是不会再长了。添加 OR 后它的工作速度比 LIKE "%...%" OR LIKE "%...%"
谁能告诉我我做错了什么?
不幸的是,全文索引 have some limitations,无法正确合并两个独立全文搜索的结果就是其中之一:
The Index Merge optimization algorithm has the following known limitations:
- [...]
- Index Merge is not applicable to full-text indexes.
幸运的是,全文搜索可能更复杂,因此您可以自己合并搜索。您的第二个查询可以写成单个搜索,使用:
SELECT * FROM product WHERE
MATCH(name) AGAINST('(+something -other) (+some -word)' IN BOOLEAN MODE)
这定义了两个搜索集,如果两个 (...)
中的任何一个匹配都可以 - 这是一个 or
.
或者,您可以使用 union
而不是 or
,这允许 MySQL 实际上 运行 两个独立的全文搜索,然后合并两个结果,这基本上就是您的想法:
SELECT * FROM product WHERE
MATCH(name) AGAINST('+some -word' IN BOOLEAN MODE)
UNION
SELECT * FROM product WHERE
MATCH(name) AGAINST('+something -other' IN BOOLEAN MODE)
这也适用于更复杂的情况,例如合并对不同列的搜索,但如果您想做 or
.