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

Mysql show different results between 2 servers with the same data for FULLTEXT index

我有一个 Mysql 5.7.19 的本地环境(在 windows 10 Pro French 上)和一个 Mysql 5.7.31(Ubuntu Linux 16.04.5).

数据从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 个结果
产品环境 => 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 上的更多数据实际上是因为新配方但没有结果。

relevancy score是根据完整table的内容计算的:

InnoDB uses a variation of the “term frequency-inverse document frequency” (TF-IDF) weighting system to rank a document's relevance for a given full-text search query. The TF-IDF weighting is based on how frequently a word appears in a document, offset by how frequently the word appears in all documents in the collection. In other words, the more frequently a word appears in a document, and the less frequently the word appears in the document collection, the higher the document is ranked.

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

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

所以分数本身的绝对值通常不是一个很好的过滤标准,例如使用您的 where score > 1,但作为对您获得的结果进行排序的一种方式,例如用 order by score desc,通常包括一个 limit.

您不太可能找到一般情况下有意义的良好绝对最小值(0 除外):

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

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