Mysql 在 FULLTEXT 索引具有相同数据的 2 台服务器之间显示不同的结果

Posted

技术标签:

【中文标题】Mysql 在 FULLTEXT 索引具有相同数据的 2 台服务器之间显示不同的结果【英文标题】:Mysql show different results between 2 servers with the same data for FULLTEXT index 【发布时间】:2020-12-06 08:02:47 【问题描述】:

我有一个带有 mysql 5.7.19(在 Windows 10 Pro French 上)的本地环境和一个带有 Mysql 5.7.31(Ubuntu Linux 16.04.5)的 prod 服务器。

数据从 Prod 同步到本地 ENV。 我有 3 列的全文索引和一个简单的请求:

SELECT MATCH (r0_.title, r0_.description, r0_.tag_text)
       AGAINST ('+poulet* +carotte*' IN BOOLEAN MODE) AS sclr_0,
       r0_.id AS id_1, r0_.title AS title_2, r0_.description AS description_3,
       r0_.url AS url_4, r0_.image AS image_5, r0_.slug AS slug_6, r0_.click AS click_7, r0_.tag_text AS tag_text_8, r0_.active AS active_9, r0_.created_at AS created_at_10, r0_.updated_at AS updated_at_11
    FROM recipe r0_
    WHERE r0_.active = 1
    HAVING sclr_0 >= 1
    ORDER BY sclr_0 DESC;

在本地环境 => 98 个结果 在 prod env => 0 结果

创建架构:

CREATE TABLE `recipe` (
  `id` int(11) NOT NULL,
  `blog_id` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `description` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `url` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `image` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `slug` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `click` smallint(6) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `tag_text` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `active` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ALTER TABLE `recipe`
  ADD PRIMARY KEY (`id`),
  ADD KEY `IDX_DA88B137DAE07E97` (`blog_id`),
  ADD KEY `IDX_DA88B1374B1EFC02` (`active`),
  ADD KEY `IDX_DA88B1378B8E8428` (`created_at`);
ALTER TABLE `recipe` ADD FULLTEXT KEY `IDX_DA88B1372B36786B6DE44026D5841871`
        (`title`,`description`,`tag_text`);

更多关于 Prod 的数据实际上是因为新配方但没有结果。

【问题讨论】:

选择您在本地获得的结果。在 prod 上,在没有当前 where 子句的情况下运行查询,但将其替换为 WHERE id = the_id_you_picked_on_local。检查active 的分数和值是否符合您的预期和/或该行是否存在。将您的发现添加到您的问题中。 对于最大的数字在本地:10.884532928466797 在产品服务器上:0.19886906445026398 为什么相同数据会有这种差异? 分数基于完整表格中的相关性(例如,您的搜索词出现在其他行中的频率越高,分数越低),参见例如here 所以如果你添加了很多胡萝卜收据来刺激,它可能会降低那里的分数。无论如何,绝对值没有太多意义,它的主要目标是对结果进行排序。彼此。主要做类似:order by score desc limit 20,甚至可以raise questions。 Solarflare 有解释(并且应该作为答案)。 HAVING sclr_0 >= 1 在存在不同的行集时以不同的方式删除“匹配”。 我不明白为什么相同的数据集,没有与分数相同的结果。我明白当我有更多结果时,分数会更低但数据相同!juste 的问题一个限制和订单分数,如果我这样做的限制为 40,如果有 25 个结果,另一个与查询没有任何匹配...... 【参考方案1】:

relevancy score是根据完整表格的内容计算出来的:

InnoDB 使用“词频-逆文档频率”(TF-IDF) 加权系统的变体来对给定全文搜索查询的文档相关性进行排名。 TF-IDF 权重基于一个词在文档中出现的频率,抵消了该词在集合中所有文档中出现的频率。换句话说,一个词在文档中出现的频率越高,而该词在文档集合中出现的频率越低,文档的排名就越高。

这里的“文档”表示单行,“文档集合”表示所有行。该手册包含确切的公式,但重要的是:由于与本地相比,您在 prod 上的食谱更多,因此得分会有所不同。如果你例如添加更多包含胡萝卜的食谱,分数会下降,如果您添加的食谱不包含您的搜索词,则分数会上升。

这与单个结果本身的实际效果完全无关!炖鸡肉胡萝卜非常适合您的搜索,但如果您的数据库中还有胡萝卜蛋糕的食谱,则绝对分数会有所不同。

因此,分数本身的绝对值通常不是过滤的好标准,例如使用您的where score > 1,但作为一种订购结果的方式,例如带有order by score desc,通常包括limit

一般情况下,您不太可能找到适合您的分数的绝对最小值(0 除外):

如果您现在发现一个不错的价值,如果胡萝卜变得更受欢迎并且您为这些添加食谱(类似于您在 prod 上的经验),那么在 2 周内它可能太高了。反之亦然,如果您使用特定值 1 来消除不需要的、较低分数的结果,如果您添加与胡萝卜无关的食谱,它们可能会在 2 周内重新出现 - 不是因为那些不需要的结果突然变得更好,而是因为它们变成了比较少见。 如果您找到适合包含胡萝卜的搜索的好值,则它可能不是其他搜索词的好值。如果你例如搜索一种常见的成分,可能是“糖”,即使绝对值较低,您仍然会期望结果包含“糖” - 只是因为它比胡萝卜更常用。

但是一个经常使用sugar这个词的食谱(因为它可能是一种重要的成分,也许是焦糖的食谱)将比只提到一次(“加点糖”)的食谱得分更高,因此您可以使用该值对结果进行相对排序。

【讨论】:

很好的解释。但我不明白为什么使用相同的数据,结果不一样?如果我让where score > 0 没问题,而且我没有这个词没有结果? 相关性可能来自Mysql中的所有基础?因为唯一的区别是其他数据库我认为这个词的行数最多 相关性不是基于整个数据库,而是基于全文索引的内容(例如,该表的 3 列中的所有数据)(我希望我说清楚了,它是手册所说的“文档集合”)。需要注意的重要一点是:如果你有更多的行,它就不再是相同的数据了! >0 总是有效的(意思是:“找到”),你实际上可以使用where match(...) against(...),甚至不用说>0,这只是意味着“有一个匹配”。如果您选择任何大于 0 的特定值,您将遇到所描述的问题。

以上是关于Mysql 在 FULLTEXT 索引具有相同数据的 2 台服务器之间显示不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

MySQL全文索引 FULLTEXT索引和like的区别

mysql索引有几种

mysql 索引有几种类型

mysql索引都有哪些

[DB] MySQL 索引分类

MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有啥区别?各适用于啥场合?