全文搜索导致“FULLTEXT 初始化”花费大量时间

hic*_*123 11 mysql innodb full-text-search

我目前正在尝试针对 Stack Overflow 评论的数据转储运行一些查询。这是架构的样子:

CREATE TABLE `socomments` (
  `Id` int(11) NOT NULL,
  `PostId` int(11) NOT NULL,
  `Score` int(11) DEFAULT NULL,
  `Text` varchar(600) NOT NULL,
  `CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `UserId` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `idx_socomments_PostId` (`PostId`),
  KEY `CreationDate` (`CreationDate`),
  FULLTEXT KEY `Text` (`Text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)

我对表运行了这个查询,它运行得非常慢(它确实有 2900 万行,但它有一个全文索引):

SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)
Run Code Online (Sandbox Code Playgroud)

所以我分析了它,结果是:

|| Status                     || Duration ||
|| starting                   || 0.000058 ||
|| checking permissions       || 0.000006 ||
|| Opening tables             || 0.000014 ||
|| init                       || 0.000019 ||
|| System lock                || 0.000006 ||
|| optimizing                 || 0.000007 ||
|| statistics                 || 0.000013 ||
|| preparing                  || 0.000005 ||
|| FULLTEXT initialization    || 207.1112 ||
|| executing                  || 0.000009 ||
|| Sending data               || 0.000856 ||
|| end                        || 0.000004 ||
|| query end                  || 0.000004 ||
|| closing tables             || 0.000006 ||
|| freeing items              || 0.000059 ||
|| logging slow query         || 0.000037 ||
|| cleaning up                || 0.000046 ||
Run Code Online (Sandbox Code Playgroud)

如您所见,它在 FULLTEXT 初始化中花费了很长时间。这是正常的吗?如果没有,我该如何解决?

小智 6

如果您使用 InnoDB FULLTEXT 索引,如果您正在查询具有大量已删除行的表,则查询通常会挂在“FULLTEXT 初始化”状态。在 InnoDB 的 FULLTEXT 实现中,在对受影响的表运行后续 OPTIMIZE 操作之前,不会修剪已删除的行。参见:https : //dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html

要删除已删除记录的全文索引条目,您必须在索引表上使用 innodb_optimize_fulltext_only=ON 运行 OPTIMIZE TABLE 以重建全文索引。

还可以通过查询information_schema.innodb_ft_deleted 来检查已删除但未清除的记录数

要解决此问题,应定期对具有 InnoDB FULLTEXT 索引的表运行 OPTIMIZE TABLE。


Rol*_*DBA 5

其他人发现这是一个麻烦的情况

由于MySQL 文档在此线程状态上非常简洁

全文初始化

服务器正准备执行自然语言全文搜索。

你唯一的办法就是用更少的数据做准备。如何 ?

建议#1

再看看你的查询。它正在选择所有列。我会重构查询以仅从socomments. 然后,将那些检索到的 id 加入到socomments表中。

SELECT B.* FROM
(SELECT id FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)) A
LEFT JOIN socomments B USING (id);
Run Code Online (Sandbox Code Playgroud)

这可能会产生一个更丑陋的 EXPLAIN 计划,但我认为分析会变得更好。基本思想是:如果你有一个激进的全文搜索,让它在那个FULLTEXT initialization阶段收集最少的数据,从而减少时间。

我之前已经推荐过很多次了

建议#2

请确保您设置的是基于 InnoDB 的 FULLTEXT 选项,而不是 MyISAM 的选项。您应该关注的两个选项是

想一想。文本字段是 VARCHAR(600)。假设平均值是 300 字节。你有 29,000,000 百万个。那将是一点点 8GB。也许增加innodb_ft_cache_sizeinnodb_ft_total_cache_size也可能有所帮助。

确保您有足够的 RAM 用于更大的 InnoDB FULLTEXT 缓冲区。

试一试 !!!


归档时间:

查看次数:

12443 次

最近记录:

8 年,3 月 前