跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

mysql优化器如何决定是否使用全文索引_解析词法分析与索引检索过程

全文索引不会被优化器自动选用,必须显式使用MATCH...AGAINST语法触发;中文需指定ngram分词器,否则可能无结果;不支持ORDER BY/GROUP BY加速;性能瓶颈常在后续过滤条件,需配合其他索引优化。 全文索引不会被优化器“自动选中” MySQL 优化器在生成执行计划时,
EXPLAIN
中的
key
列永远为
NULL
,哪怕表上建了
FULLTEXT
索引。这不是失效,而是设计如此:全文检索必须显式使用
MATCH ... AGAINST
语法触发,优化器不把它当作普通索引参与成本估算。 常见误解是把全文查询写成
WHERE content LIKE '%关键词%'
或
WHERE content = 'xxx'
,这类写法完全绕过全文索引,只能走全表扫描或普通 B+ 树索引(如果存在且匹配)。 必须用
MATCH(content) AGAINST('关键词')
才能激活全文索引
AGAINST
的第二个参数决定模式:
IN NATURAL LANGUAGE MODE
(默认)、
IN BOOLEAN MODE
、
WITH QUERY EXPANSION
即使列上有
FULLTEXT
索引,
ORDER BY content
或
GROUP BY content
也不会利用它——全文索引不支持排序或分组加速 全文索引的词法分析由分词器控制,不是 SQL 层逻辑 InnoDB 全文索引的分词行为发生在存储引擎层,与 SQL 解析器分离。默认使用
ngram
分词器(适用于中文/日文),但需在建表或添加索引时显式指定:
ALTER TABLE articles ADD FULLTEXT INDEX ft_title_content (title, content) WITH PARSER ngram;
没加
WITH PARSER ngram
,对中文字段执行
MATCH ... AGAINST
可能返回空结果——因为默认分词器按空格和标点切分,中文无空格,整个字段被当做一个“单词”,几乎无法命中。
ngram_token_size
参数控制中文分词粒度,默认为 2(即按双字切分),可设为 1(单字)或 3(三字),但值越小索引体积越大 分词结果存于内部 FTS auxiliary tables(如
FTS_0000000000000123_0000000000000124_INDEX_1
),不可直接查,也不参与
EXPLAIN
MyISAM 的全文索引用不同分词机制,且不支持
ngram
,跨引擎迁移时行为会突变 全文查询性能瓶颈常不在索引本身,而在匹配后过滤
MATCH ... AGAINST
返回的是文档 ID 和相关性评分,但 MySQL 默认不缓存中间结果。如果后续跟了复杂
WHERE
条件或
JOIN
,引擎可能先取出全部匹配文档 ID,再回主表逐行过滤——这会导致大量随机 I/O。 例如: MySQL(Linux) MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。 下载
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE) AND status = 'published' AND create_time > '2025-01-01';
这里
status
和
create_time
若无联合索引覆盖,就可能让全文检索的优势被抵消。 优先把高频过滤条件挪到
MATCH
外部,并确保这些列有独立索引或与全文字段组成组合索引(注意:InnoDB 不支持全文索引与其他类型索引混合)
IN BOOLEAN MODE
支持
+
、
-
、
*
等操作符,能提前排除大量无效文档,比自然语言模式更可控 相关性评分(
RELEVANCE
)无法用索引排序,
ORDER BY MATCH(...) AGAINST(...)
会触发文件排序(
Using filesort
) 全文索引重建与碎片问题容易被忽略 InnoDB 全文索引更新是异步的:INSERT/UPDATE 后,变更先写入
FTS insert buffer
,后台线程再批量合并进倒排索引。DELETE 不立即清理倒排项,而是记入
DELETED
辅助表。长时间运行后,索引会膨胀、查询变慢。 没有类似
OPTIMIZE TABLE
对全文索引的“一键整理”命令。有效手段只有: 执行
OPTIMIZE TABLE articles
—— 这会重建整张表,包括全文索引,但会锁表,且耗时长 导出数据 → 删除全文索引 → 重建表 → 导入 → 重新加
FULLTEXT
索引(适合低峰期维护) 监控
INFORMATION_SCHEMA.INNODB_FT_CONFIG
表中的
optimize_count
,值持续增长说明合并滞后 真正麻烦的是:全文索引一旦创建,就不能修改分词器类型或字段列表,只能删掉重建——而重建期间新写入的数据可能丢失分词,导致搜索不一致。

相关文章