乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

全文检索函数

导学

当数据量增大时,LIKE '%关键词%' 的模糊查询会触发全表扫描,性能急剧下降。MySQL 的全文检索(Full-Text Search)通过建立全文索引,配合 MATCH ... AGAINST 语法,实现对大文本字段的高效关键词搜索——支持自然语言模式、布尔模式,甚至查询扩展。

定义

全文检索:基于全文索引(FULLTEXT INDEX),使用 MATCH(列名) AGAINST('关键词') 语法进行文本搜索的查询方式。仅适用于 CHAR、VARCHAR、TEXT 类型字段。

核心语法

创建全文索引

-- 建表时创建
CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    content TEXT,
    FULLTEXT INDEX ft_idx (title, content)
) ENGINE=InnoDB;

-- 给已有表添加
ALTER TABLE articles ADD FULLTEXT INDEX ft_idx (title, content);

全文检索查询

-- 自然语言模式(默认)
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('关键词');

-- 布尔模式
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);

-- 查询扩展模式
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('MySQL' WITH QUERY EXPANSION);
模式说明
自然语言模式(默认)自动分词,排除 50% 阈值(出现超过 50% 行的词被忽略),按相关性排序
布尔模式支持 +(必须包含)、-(必须排除)、*(前缀匹配)、""(短语匹配)
查询扩展模式先搜索一次,再用结果中的高频词扩展搜索,适合短查询

演示数据准备

DROP TABLE IF EXISTS articles;

CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    content TEXT,
    FULLTEXT INDEX ft_idx (title, content)
) ENGINE=InnoDB;

INSERT INTO articles (title, content) VALUES
('MySQL 索引优化指南', '本文介绍 MySQL 中 B+Tree 索引的原理,以及如何通过 EXPLAIN 分析查询性能。'),
('MySQL 事务与锁机制', '深入讲解 InnoDB 的 MVCC 多版本并发控制,以及行锁、间隙锁的实现原理。'),
('Oracle 数据库迁移到 MySQL', '从 Oracle 迁移到 MySQL 的注意事项,包括数据类型映射、SQL 语法差异等。'),
('MySQL 主从复制配置', '手把手教你配置 MySQL 5.7 的异步复制,包括 binlog 格式选择和故障切换。');

当前 articles 表中的完整数据如下:

idtitlecontent
1MySQL 索引优化指南本文介绍 MySQL 中 B+Tree 索引的原理...
2MySQL 事务与锁机制深入讲解 InnoDB 的 MVCC 多版本并发控制...
3Oracle 数据库迁移到 MySQL从 Oracle 迁移到 MySQL 的注意事项...
4MySQL 主从复制配置手把手教你配置 MySQL 5.7 的异步复制...

SQL 示例

场景一:自然语言模式全文检索

当前数据状态:见上文 articles 表完整数据。

执行语句:

SELECT id, title,
       MATCH(title, content) AGAINST('MySQL 优化') AS relevance
FROM articles
WHERE MATCH(title, content) AGAINST('MySQL 优化');

操作后结果:

idtitlerelevance
1MySQL 索引优化指南0.258668...
4MySQL 主从复制配置0.145258...
2MySQL 事务与锁机制0.124123...

结果解读:

  • MATCH(...) AGAINST(...) 在 WHERE 子句中用于过滤匹配行
  • 在 SELECT 子句中返回相关性评分(relevance),值越大越相关
  • 结果自动按相关性降序排列(MySQL 内部优化)
  • 第 3 条 "Oracle 数据库迁移到 MySQL" 也包含 "MySQL",但相关性较低,未进入前三

注意:自然语言模式有一个"50% 阈值"陷阱——如果某个词出现在超过 50% 的行中,它会被忽略。例如搜索 "MySQL" 单独一个词时,由于 4 行中有 3 行包含 "MySQL"(75% > 50%),可能返回空结果!

场景二:布尔模式(精确控制匹配逻辑)

当前数据状态:见上文 articles 表完整数据。

执行语句:

-- 必须包含 MySQL,必须不包含 Oracle
SELECT id, title FROM articles
WHERE MATCH(title, content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);

-- 必须包含 MySQL,包含 优化 或 索引 之一
SELECT id, title FROM articles
WHERE MATCH(title, content) AGAINST('+MySQL (优化 索引)' IN BOOLEAN MODE);

-- 前缀匹配:匹配 "配置"、"配置方法"、"配置文件" 等
SELECT id, title FROM articles
WHERE MATCH(title, content) AGAINST('配置*' IN BOOLEAN MODE);

操作后结果:

+MySQL -Oracle:

idtitle
1MySQL 索引优化指南
2MySQL 事务与锁机制
4MySQL 主从复制配置

+MySQL (优化 索引):

idtitle
1MySQL 索引优化指南

结果解读:

  • + 前缀:词必须出现(AND)
  • - 前缀:词必须不出现(NOT)
  • 无前缀:词可选出现(OR)
  • () 分组:控制优先级
  • * 后缀:前缀匹配(如 配置* 匹配 "配置" 开头的词)
  • 布尔模式没有 50% 阈值,适合搜索高频词

场景三:短语匹配(精确短语搜索)

当前数据状态:见上文 articles 表完整数据。

执行语句:

-- 精确匹配短语 "MySQL 5.7"
SELECT id, title FROM articles
WHERE MATCH(title, content) AGAINST('"MySQL 5.7"' IN BOOLEAN MODE);

操作后结果:

idtitle
4MySQL 主从复制配置

结果解读:"MySQL 5.7" 用双引号包裹,表示精确短语匹配。只有第 4 条包含完整的 "MySQL 5.7",其他条虽然包含 "MySQL" 和 "5.7" 但不连续,不匹配。

场景四:查询扩展模式(解决短查询召回不足)

当前数据状态:见上文 articles 表完整数据。

执行语句:

-- 普通搜索 "InnoDB"
SELECT id, title FROM articles WHERE MATCH(title, content) AGAINST('InnoDB');

-- 查询扩展:先用 InnoDB 搜一次,再用结果中的高频词扩展搜索
SELECT id, title FROM articles
WHERE MATCH(title, content) AGAINST('InnoDB' WITH QUERY EXPANSION);

操作后结果:

普通搜索:

idtitle
2MySQL 事务与锁机制

查询扩展:

idtitle
2MySQL 事务与锁机制
1MySQL 索引优化指南
4MySQL 主从复制配置

结果解读:

  • 普通搜索只找到直接包含 "InnoDB" 的第 2 条
  • 查询扩展模式先搜 "InnoDB",发现第 2 条还包含 "MySQL"、"MVCC"、"锁" 等词,然后用这些高频词再次搜索
  • 结果召回更多相关文档(第 1 条讲 MySQL 索引,第 4 条讲 MySQL 复制),即使它们不直接包含 "InnoDB"
  • 适合用户输入很短(如一个词)时扩展召回

场景五:全文检索 vs LIKE 的性能对比

当前数据状态:基于 articles 表。

执行语句:

-- LIKE 模糊查询(全表扫描)
EXPLAIN SELECT * FROM articles WHERE content LIKE '%MySQL%';

-- 全文检索(使用全文索引)
EXPLAIN SELECT * FROM articles WHERE MATCH(title, content) AGAINST('MySQL');

操作后结果:

LIKE '%MySQL%' 的 EXPLAIN:

idselect_typetabletypepossible_keyskeyrows
1SIMPLEarticlesALLNULLNULL4

MATCH ... AGAINST('MySQL') 的 EXPLAIN:

idselect_typetabletypepossible_keyskeyrows
1SIMPLEarticlesfulltextft_idxft_idx1

结果解读:

  • LIKE '%关键词%':type = ALL,全表扫描,无法使用普通索引
  • MATCH ... AGAINST:type = fulltext,使用全文索引 ft_idx
  • 数据量越大,性能差距越明显。全文检索在百万级文本数据中仍能保持毫秒级响应

常见误区

误区正解
"全文检索可以替代所有 LIKE 查询"不能。全文检索只支持 CHAR/VARCHAR/TEXT,不支持前缀模糊匹配(如 LIKE '%abc%' 中的中间匹配),且对短词(默认 < 4 字符)不索引。
"全文索引和普通索引一样,建了就生效"不是。全文索引只支持 MATCH ... AGAINST 语法,普通 WHERE 条件不会使用它。
"自然语言模式搜索高频词一定能找到"不一定。50% 阈值会导致高频词被忽略。搜索 "MySQL" 如果出现在超过 50% 的行中,结果为空。
"InnoDB 和 MyISAM 的全文检索完全一样"不完全一样。MyISAM 支持 ft_min_word_len 配置最小词长;InnoDB 使用 innodb_ft_min_token_size(默认 3)。InnoDB 5.7 才引入全文索引,功能比 MyISAM 稍弱。
"中文全文检索和英文一样直接用"不是。MySQL 默认按空格分词,中文没有空格,需要额外配置(如 ngram 解析器,MySQL 5.7.6+ 支持)或使用第三方插件。
"全文索引可以建在任意字段上"不能。只能建在 CHAR、VARCHAR、TEXT 类型上,且同一表只能有一个全文索引(InnoDB 限制已解除)。

面试考点

Q:全文检索和 LIKE '%关键词%' 的区别?

  1. 全文检索使用倒排索引,LIKE '%...%' 无法使用索引,全表扫描。2. 全文检索支持相关性排序、布尔逻辑、查询扩展;LIKE 只有简单匹配。3. 全文检索有最小词长和 50% 阈值限制;LIKE 无限制。4. 全文检索只适用于文本字段;LIKE 适用于任何字符串字段。

Q:什么是 50% 阈值?如何解决?

自然语言模式下,出现在超过 50% 行中的词被视为"太常见"而被忽略。解决:1. 改用布尔模式(IN BOOLEAN MODE),无 50% 阈值;2. 使用子查询缩小数据集后再全文检索;3. 使用查询扩展模式。

Q:InnoDB 和 MyISAM 的全文索引有什么区别?

MyISAM 从早期就支持全文索引,功能成熟;InnoDB 从 5.6.4 开始支持,5.7 功能完善。主要区别:InnoDB 支持事务(全文索引随事务提交/回滚),MyISAM 不支持;InnoDB 使用 innodb_ft_min_token_size(默认 3),MyISAM 使用 ft_min_word_len(默认 4);InnoDB 支持多全文索引,MyISAM 早期限制一个。

Q:中文全文检索怎么做?

MySQL 默认按空格分词,中文无空格,直接全文检索效果差。解决方案:1. MySQL 5.7.6+ 使用 ngram 解析器(WITH PARSER ngram),按字符 n-gram 分词;2. 使用第三方中文分词插件(如 jieba、 SCWS);3. 程序层分词后存倒排表。

Q:MATCH 在 SELECT 和 WHERE 中的区别?

WHERE MATCH(...) AGAINST(...) 用于过滤匹配行;SELECT MATCH(...) AGAINST(...) 返回相关性评分(浮点数),可用于排序或展示。两者可以同时在一条 SQL 中使用。

小结

  • 全文检索通过 FULLTEXT INDEX + MATCH ... AGAINST 实现高效文本搜索
  • 三种模式:自然语言(默认,有 50% 阈值)、布尔模式(精确逻辑控制)、查询扩展(短查询召回增强)
  • 性能远超 LIKE '%...%'(全表扫描 vs 倒排索引)
  • 中文需要额外配置(ngram 解析器或第三方分词)
  • 适合文章标题/内容搜索、日志检索、商品描述搜索等文本密集型场景

下一章引子:全文检索解决了大文本搜索的效率问题,但日常运维中,我们还需要频繁查看数据库的状态信息——表结构、索引列表、引擎状态等。SHOW 语句是 MySQL 运维的"瑞士军刀"。

上一页
日期函数