当前位置: 首页 > news >正文

MySQL 全文索引实战:搜索功能的正确打开方式

开场白

做搜索功能的时候,很多人第一反应是 LIKE ‘%关键词%’,数据量小的时候没问题,数据一大直接全表扫描。我之前有个项目,商品表的 LIKE 搜索在 50 万条数据时就要 3 秒以上,根本没法用。后来上了全文索引,查询时间降到毫秒级。不过全文索引也有自己的坑——中文分词、停用词、最小搜索长度,这些搞不明白一样用不好。

全文索引基础

创建全文索引

-- 建表时创建CREATETABLEarticles(idBIGINTPRIMARYKEYAUTO_INCREMENT,titleVARCHAR(200),contentTEXT,FULLTEXTINDEXft_title_content(title,content));-- 已有表添加ALTERTABLEarticlesADDFULLTEXTINDEXft_title_content(title,content);-- 单列全文索引ALTERTABLEarticlesADDFULLTEXTINDEXft_content(content);

基本查询

-- 自然语言模式(默认)SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('数据库优化');-- 布尔模式SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('+MySQL -Oracle'INBOOLEANMODE);-- 查询扩展模式SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('数据库'WITHQUERY EXPANSION);

MATCH 里的列必须和全文索引定义的列完全一致,顺序也要一样。如果索引是(title, content),查询必须写MATCH(title, content),不能写MATCH(content, title)

三种搜索模式

自然语言模式

默认模式,按相关性排序:

SELECT*,MATCH(title,content)AGAINST('数据库优化')ASscoreFROMarticlesWHEREMATCH(title,content)AGAINST('数据库优化')ORDERBYscoreDESC;

相关性分数基于词频(TF)和逆文档频率(IDF),MySQL 内部计算,不需要我们操心。

搜索的是"数据库"和"优化"两个词的 OR 组合——包含任意一个词的记录都会返回。

布尔模式

精确控制搜索逻辑:

-- 必须包含 MySQL,不能包含 OracleSELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('+MySQL -Oracle'INBOOLEANMODE);-- 必须同时包含 MySQL 和 优化SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('+MySQL +优化'INBOOLEANMODE);-- 包含 MySQL 或 OracleSELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('MySQL Oracle'INBOOLEANMODE);-- 包含以数据开头的词SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('数据*'INBOOLEANMODE);-- 必须包含 MySQL,且优化权重更高SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('+MySQL >优化'INBOOLEANMODE);

布尔模式的操作符:

操作符含义
+必须包含
-不能包含
可选,包含则加分
*通配符(只能后缀)
“”短语匹配
> <增减权重
()分组
~取反(降低相关性)

短语匹配要特别注意:

-- 精确匹配"数据库优化"这个短语SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('"数据库优化"'INBOOLEANMODE);

查询扩展模式

两步搜索:先搜一次,用结果中的词再搜一次。适合用户搜索词太少、结果不够的情况。

SELECT*FROMarticlesWHEREMATCH(title,content)AGAINST('数据库'WITHQUERY EXPANSION);

但这个模式容易返回不相关的结果,慎用。

中文分词问题

这是全文索引最大的坑。MySQL 默认的分词器按空格和标点分词,中文没有空格,整段中文会被当成一个词:

-- content = "MySQL数据库优化实战"-- 默认分词器会把"MySQL数据库优化实战"当成一个整体词-- 搜"数据库"搜不到!SELECT*FROMarticlesWHEREMATCH(content)AGAINST('数据库');

解决方案一:ngram 分词器(MySQL 5.7.6+)

-- 建表时指定 ngram 分词器CREATETABLEarticles(idBIGINTPRIMARYKEYAUTO_INCREMENT,titleVARCHAR(200),contentTEXT,FULLTEXTINDEXft_title_content(title,content)WITHPARSER ngram);-- 添加索引时指定ALTERTABLEarticlesADDFULLTEXTINDEXft_content(content)WITHPARSER ngram;

ngram 分词器按固定长度把文本切成片段,默认 n=2(二元分词):

"数据库优化" → "数据", "据库", "库优", "优化"

ngram 的 n 值通过ngram_token_size参数配置,范围 1-10,默认 2。改这个参数需要重启 MySQL:

# my.cnf [mysqld] ngram_token_size = 2

n=2 意味着搜索词至少 2 个字符才能命中。搜单个字(比如"数")搜不到。

解决方案二:手动分词

在插入数据前,用应用层分词器(比如 IK、jieba)把中文文本切成词,用空格拼接后存储:

-- 原文:"MySQL数据库优化实战"-- 分词后存储:"MySQL 数据库 优化 实战"INSERTINTOarticles(title,content)VALUES('MySQL数据库优化实战','MySQL 数据库 优化 实战');```这种方式灵活,分词质量高,但增加了应用层复杂度。 ## 全文索引的配置参数 ### ft_min_word_len / innodb_ft_min_token_size 最小索引词长度,默认 InnoDB 是 3,MyISAM 是 4。长度小于这个值的词不会被索引。 ```ini# my.cnf[mysqld]innodb_ft_min_token_size=1# InnoDBft_min_word_len=1# MyISAM

改成 1 之后需要重建全文索引:

ALTERTABLEarticlesDROPINDEXft_content;ALTERTABLEarticlesADDFULLTEXTINDEXft_content(content)WITHPARSER ngram;

innodb_ft_cache_size

全文索引缓存大小,默认 32MB。批量插入大量数据时,增大这个值可以提升索引构建速度。

ft_query_expansion_limit

查询扩展模式的最大扩展词数,默认 20。

全文索引 vs LIKE

维度全文索引LIKE
索引利用走全文索引前缀匹配走索引,%xx%全表扫描
搜索精度分词匹配,支持相关性排序模糊匹配,无排序
中文支持需要 ngram 或手动分词直接支持
写入性能需要维护索引,写入较慢无额外开销
存储开销索引占额外空间无额外空间

简单说:精确匹配用 LIKE,搜索功能用全文索引。

实战建议

  1. 搜索场景用全文索引,匹配场景用 LIKE——别拿全文索引当万能的
    1. 中文必须用 ngram 分词器——否则搜不到东西
    1. 布尔模式的 + 和 - 组合最实用——精确控制搜索结果
    1. 注意最小搜索长度——ngram_token_size=2 时搜单个字搜不到
    1. 全文索引会降低写入性能——不适合频繁更新的表
    1. 数据量特别大时考虑 Elasticsearch——MySQL 全文索引有上限,亿级数据还是上 ES 吧

小结

全文索引是 MySQL 内置的搜索方案,适合中小规模的搜索需求。关键点就三条:中文用 ngram 分词器,查询用布尔模式精确控制,搜索长度注意最小值限制。如果你的搜索需求很复杂(拼音搜索、同义词、高亮等),还是得上 Elasticsearch,MySQL 全文索引搞不定。

相关阅读

  • MySQL 官方文档 - Full-Text Search
    • ngram 分词器
    • 全文索引布尔模式
http://www.jsqmd.com/news/880029/

相关文章:

  • 2026 四川 H 型钢优质供应商推荐|盛世钢联全品类现货批发,生产厂家与采购指南 - 四川盛世钢联营销中心
  • CoolProp热物理计算终极指南:从入门到精通的热力学工具
  • 太顶了!只需输入需求,这几款一键生成论文工具自动生成毕业论文初稿!
  • NS模拟器自动化管理系统:简化游戏兼容性配置的解决方案
  • 开源AI工具真能替代商业方案?2024最新Benchmark数据揭示92%团队忽略的关键短板
  • 【稻米计数】基于matlab形态学稻米计数【含Matlab源码 15562期】
  • 上海嘉定区宸智雅筑装饰官方联系方式 合作电话 官方网站官网 - 元点智创
  • 2026 深圳劳动纠纷律师怎么选?专业度优先避坑指南 - 从来都是英雄出少年
  • 利用Taotoken实现多模型备选方案以提升业务连续性
  • equalsIgnoreCase忽略大小写直接对比
  • 2026年4月墙改梁加固企业推荐,粘钢植筋加固/房屋碳纤维加固/建筑物加固/裂缝修补加固,墙改梁加固施工厂家怎么选择 - 品牌推荐师
  • 品牌生死局——2026GEO优化公司全景测评必选指南 - GEO优化
  • 3分钟让AI自动分层?LayerDivider如何拯救你的PSD编辑噩梦
  • 2026年一键生成论文工具实测精选:5款神器从构思到提交全流程护航
  • AI 时代产品经理生存与进化指南
  • Gitclub第三次团队作业——Alpha 冲刺计划
  • Chrome配Burp代理全链路配置指南:端口、证书与命令行三要素
  • 2026年4月比较好的测漏公司推荐,地暖管道清洗/墙面测漏/墙面漏水维修/水管测漏/厨房漏水维修,测漏企业推荐 - 品牌推荐师
  • 【教育科技爆款内容生产核心】:用ChatGPT批量生成带答案解析+难度分级+认知维度标签的脑筋急转弯(附可商用JSON Schema)
  • 全球公域AI底层架构:一个字符唤醒世界
  • 从零开发游戏需要学习的c#模块,第二十四章(场景管理 —— 标题、游戏、结束画面)
  • 2026 四川螺纹钢优质供应商推荐|盛世钢联全品类现货批发,价格行情与采购指南 - 四川盛世钢联营销中心
  • 超人级安全敏捷多智能体强化学习飞行动力系统
  • 企业团队如何利用Taotoken CLI工具统一配置开发环境与API密钥
  • 华为OD机试 新系统 C++实现【社交网络相同爱好好友查询】
  • 卖不干胶标签怎么找客户?下游工厂在哪里
  • 一、从“流量高地”到“全意图心智”——2026深圳GEO优化公司全景洞察 - GEO优化
  • 2026爆火!5款AI写作辅助平台实测,治愈文献焦虑,初稿撰写快人一步
  • 从零开发游戏需要学习的c#模块,第二十三章(存档与高分系统)
  • C#学习(26_05_24)