全文搜索按相关性分数排序

Posted

技术标签:

【中文标题】全文搜索按相关性分数排序【英文标题】:Full text search sort by relevancy score 【发布时间】:2016-09-19 10:56:08 【问题描述】:

表: usersfull text searchusername 上的索引。

查询:

SELECT 
    MATCH (username) AGAINST ('shaharyar' IN NATURAL LANGUAGE MODE) AS `score`, 
    uid, 
    first_name, 
    username, 
    `status`, 
    created
FROM users
WHERE 
    MATCH (username) AGAINST ('shaharyar' IN NATURAL LANGUAGE MODE) AND 
    uid <> 164125 -- to prevent self profile search
ORDER BY 
    score DESC, 
    created DESC

问题:Match子句会执行2次吗?

我知道 mysql 默认按score降序排序,但这里我需要双重排序条件,这就是我选择该列的原因。

解释扩展:

+----+-------------+-------+----------+------------------+----------+---------+-----+------+----------+-----------------------------+
| id | select_type | table |   type   |  possible_keys   |   key    | key_len | ref | rows | filtered |            Extra            |
+----+-------------+-------+----------+------------------+----------+---------+-----+------+----------+-----------------------------+
|  1 | SIMPLE      | users | fulltext | PRIMARY,username | username |       0 |     |    1 |      100 | Using where; Using filesort |
+----+-------------+-------+----------+------------------+----------+---------+-----+------+----------+-----------------------------+

表格中有大约 150K+ 条记录。

【问题讨论】:

【参考方案1】:

是和不是。

WHERE MATCH... 将被执行若干次,从而“过滤”掉不“匹配”的行。只有剩余的行需要再次执行MATCH

另一方面,HAVING 必须对所有行(具有该 uid 的行除外)执行MATCH,构建一个包含所有这些行的临时表。只有这样HAVING 才能进行过滤。

因此,即使MATCHHAVING 版本中执行的次数更少,查询也可能会运行得更快。

确实FULLTEXT(username),不是吗?

为什么,为什么,对一个词使用全文查询??

【讨论】:

如果我创建一个包含所有过滤行的临时表以在它们上应用HAVING,它会不会与我当前的查询相同?或者我可能理解错了。除了这只是最小的例子,我将逻辑映射到其他场景。 这将与您的原始查询基本相同 - 只是因为显式创建 tmp 表而变慢。 这意味着我可以说我当前的查询非常适合该场景,并且没有办法在 SELECT 子句中获得 WHERE 条件?【参考方案2】:

认为是的。这通常使用having 子句编写:

SELECT MATCH (username) AGAINST ('shaharyar' IN NATURAL LANGUAGE MODE) AS `score`, 
       uid, first_name, username, `status`, created
FROM users
WHERE uid <> 164125 -- to prevent self profile search
HAVING score > 0
ORDER BY score DESC, created DESC;

【讨论】:

很遗憾,您的查询没有使用索引(通过解释检查)。扫描 86K+ 行。我认为它的原因是条件不在 WHERE 子句中,而是在子句之后。

以上是关于全文搜索按相关性分数排序的主要内容,如果未能解决你的问题,请参考以下文章

如何按相关性对MYSQL全文搜索结果进行排序

Mysql全文搜索,自然语言模式:按“亲密度”排序

mysql全文搜索相关性得分不正确

全文搜索基本原理(倒排索引搜索结果排序)

PostgreSQL 中的高效全文搜索,在另一列上排序

全文搜索引擎有那些、