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