繁体   English   中英

如何快速在 MySQL 中的多列中进行全文搜索?

[英]How to do fulltext search in multiple columns in MySQL, quickly?

我知道这个问题已经被问过好几次了..但是,让我解释一下。

我有一个包含 450k 用户记录(id、名字、姓氏、地址、电话号码等)的表。 我想通过他们的名字和/或他们的姓氏搜索用户。

我使用了这些查询:

SELECT * FROM correspondants WHERE nom LIKE 'Renault%' AND prénom LIKE 'r%';

SELECT * FROM correspondants WHERE CONCAT(nom, CHAR(32), prénom= LIKE 'Renault r%';

它运行良好,但持续时间太长(1.5 秒)。 这是我的问题。

为了解决这个问题,我尝试在 MATCH 和 AGAINST 两列上使用全文索引 'nom' 和 'prénom' :

SELECT * FROM correspondants WHERE MATCH(nom, prénom) AGAINST('Renault r');

它非常快(0,000 s ..)但结果很糟糕,我没有得到我应该拥有的。

例如,使用 LIKE 函数,结果为:

88623   RENAULT Rémy
91736   RENAULT Robin
202269  RENAULT Régine

(3 个结果)。

并与 MATCH/AGAINST :

327380  RENAULT Luc
1559    RENAULT Marina
17280   RENAULT Anne
(...)
88623   RENAULT Rémy
91736   RENAULT Robin
202269  RENAULT Régine
(...)
436696  SEZNEC-RENAULT  Helene
(...)

(115 个结果!)

使用“AND”搜索对两列进行快速有效的文本搜索的最佳方法是什么? (以及索引呢)

全文搜索不像LIKE字符串比较那样进行模式匹配。 全文搜索只搜索完整的单词,而不是像r%这样的片段。

还有一个字的最小大小,由ft_min_word_len配置变量控制。 为避免全文索引太大,它不会索引小于该变量的单词。 因此,搜索时会忽略短词,因此忽略r

在全文索引中也没有选择在特定位置(如字符串开头)搜索单词。 因此,您对renault的搜索可能会出现在字符串的中间。

要解决这些问题,您可以执行以下操作:

SELECT * FROM correspondants WHERE MATCH(nom, prénom) AGAINST('Renault')
  AND CONCAT(nom, CHAR(32), prénom) LIKE 'Renault r%';

这将使用全文索引来查找 450,000 行的一小部分,这些行在字符串的某处有renault一词。 然后搜索中的第二项将在没有索引帮助的情况下完成,但仅针对与第一项匹配的行子集。

该特定查询最好通过以下方式完成:

INDEX(nom, prénom)

WHERE non = 'Relault' AND prénom LIKE 'R%'

我建议你添加一个索引并将代码添加到您的应用程序,以不同的方式处理不同的请求。

不要在函数调用中隐藏索引列,例如CONCAT(nom, ...) ,它将无法使用索引; 相反,它将检查每一行,为每一行执行CONCAT ,然后执行LIKE 非常慢。

除了首字母的情况(如上),你应该尽量避免非常短的名字。 但是,这是另一种情况,您可以使用额外的代码使其工作:

WHERE nom = 'Lu'

(具有相同的索引)。 请注意,使用任何风格的MATCH可能效率低得多。

因此,如果您有完整的姓氏,请使用WHERE nom = 如果给你一个前缀,那么使用WHERE nom LIKE 'Prefix%'等可能会起作用。

FULLTEXT最适合用于将完整单词分散在较长文本中的情况,这不是您的情况,因为您已将nomprénom分开。

也许您不应该对这个模式中的任何内容使用MATCH

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM