【问题标题】:Mysql Fulltext Index with AND condition accross multiple tables is slowMysql Fulltext Index with AND condition across multiple tables is slow
【发布时间】:2022-11-12 09:37:49
【问题描述】:

我有两个具有以下结构的大表(55M 行):

CREATE TABLE `chapters` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `toc` varchar(5000) COLLATE utf8mb4_unicode_ci NOT NULL,
  `author` varchar(5000) COLLATE utf8mb4_unicode_ci NOT NULL,
  `ari_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `ari_id` (`ari_id`),
  FULLTEXT KEY `toc` (`toc`),
  FULLTEXT KEY `author` (`author`)
) ENGINE=InnoDB AUTO_INCREMENT=52251463 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

CREATE TABLE `books` (
  `ID` int(15) unsigned NOT NULL AUTO_INCREMENT,
  `Title` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `Author` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `isOpenAccess` tinyint(1) NOT NULL,
  `ari_id` bigint(20) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `ari_id` (`ari_id`),
  FULLTEXT KEY `Title` (`Title`),
  FULLTEXT KEY `Author` (`Author`),
) ENGINE=InnoDB AUTO_INCREMENT=2627161 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

我正在使用以下查询进行搜索:

SELECT b.ari_id, b.Title, b.Author, t.toc, t.author
  FROM books b
 INNER JOIN chapters t
    ON b.ari_id = t.ari_id
 WHERE MATCH(t.toc) AGAINST('power*' IN BOOLEAN MODE)
   AND b.isOpenaccess = 1 
 LIMIT 300

它在大约 12 秒内返回结果。有没有可能加快响应时间?

其次,当我尝试使用“AND”运算符从两个全文索引中搜索时,需要永远响应(146 秒)。我正在运行的查询如下:

SELECT toc, author
  FROM tocs
 WHERE MATCH(toc) AGAINST('high*' IN BOOLEAN MODE)
   AND MATCH(author) AGAINST('max*' IN BOOLEAN MODE) 
 LIMIT 300

【问题讨论】:

  • 没有 ORDER BY 的限制?什么原因?它在大约 12 秒内返回结果SELECT ari_id FROM chapters WHERE MATCH(toc) AGAINST('power*' IN BOOLEAN MODE)需要多少时间?它返回多少行?什么是不同的ari_id 金额?整个查询返回多少行(无限制)?
  • 没有 ORDER BY 的 LIMIT 更快,因为它不涉及排序“需要多少时间......”取决于有多少用户正在查询“它返回多少行?” 300 "什么是不同的 ari_id 数量?" 2.3M “整个查询返回多少行(无限制)?” 53M

标签: mysql full-text-search


【解决方案1】:

books 中,ari_id 可以是PRIMARY KEY,你可以去掉id。 (这可能会或可能不会帮助性能。)

MySQL喜欢先运行WHEREFULLTEXT部分,然后AND 与其他测试。

这个:

 WHERE MATCH(toc) AGAINST('high*' IN BOOLEAN MODE)
   AND MATCH(author) AGAINST('max*' IN BOOLEAN MODE) 

可以使用FULLTEXT(toc, author)

 WHERE MATCH(toc, author) AGAINST('high* max*' IN BOOLEAN MODE)

但它会找到额外的行。 (例如,toc 既有 high 又有 max,但 author 两者都没有。)

在对两个联接表中的每一个进行 FT 查询时,不可能使用类似的技巧。

OTOH,通过拥有一个包含所有列的第三个表以及 ari_id,可以让您将测试组合成一个 MATCH。然后进一步细化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-02
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 2022-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多