一、全文检索的基本概念

在日常开发中,我们经常遇到需要快速搜索大量文本内容的需求。比如电商平台的商品搜索、新闻网站的文章检索,这时候普通的LIKE查询就显得力不从心了。全文检索技术就是为了解决这个问题而生的。

MySQL从5.6版本开始内置了全文检索功能,它通过建立倒排索引的方式,可以快速定位包含关键词的文本记录。与传统的LIKE查询相比,全文检索有以下优势:

  1. 支持自然语言查询
  2. 支持相关性排序
  3. 支持布尔搜索
  4. 性能更高

二、MySQL全文检索的实现方案

1. 创建全文索引

首先我们需要在表上创建全文索引。假设我们有一个文章表:

-- 创建文章表
CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(200),
    content TEXT,
    FULLTEXT (title, content)  -- 创建联合全文索引
) ENGINE=InnoDB;

这里我们为title和content字段创建了一个联合全文索引。注意:

  • 全文索引只能用于InnoDB或MyISAM存储引擎
  • 每个表可以有多个全文索引
  • 索引列必须是CHAR、VARCHAR或TEXT类型

2. 基本全文检索查询

最简单的全文检索查询使用MATCH AGAINST语法:

-- 搜索包含"数据库"的文章
SELECT * FROM articles 
WHERE MATCH(title, content) AGAINST('数据库');

3. 布尔模式搜索

MySQL还支持更强大的布尔搜索:

-- 搜索必须包含"MySQL"且不包含"Oracle"的文章
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);

布尔模式支持以下操作符:

    • 必须包含
    • 必须不包含
  • 提高相关性

  • < 降低相关性
    • 通配符
  • "" 短语搜索

三、性能优化策略

1. 索引优化

全文索引的性能很大程度上取决于索引的质量:

-- 重建全文索引以优化性能
ALTER TABLE articles DROP INDEX title;
ALTER TABLE articles ADD FULLTEXT(title, content);

2. 查询优化

避免在WHERE子句中使用OR连接多个MATCH条件:

-- 不推荐的写法
SELECT * FROM articles
WHERE MATCH(title) AGAINST('MySQL') OR MATCH(content) AGAINST('MySQL');

-- 推荐的写法
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('MySQL');

3. 结果集限制

全文检索通常返回大量结果,合理使用LIMIT:

-- 只返回前20条最相关的结果
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('数据库')
ORDER BY MATCH(title, content) AGAINST('数据库') DESC
LIMIT 20;

4. 停用词处理

MySQL默认会忽略一些常见词(停用词),可以通过修改配置调整:

-- 查看当前停用词列表
SHOW VARIABLES LIKE 'ft_stopword_file';

-- 修改my.cnf添加自定义停用词
[mysqld]
ft_stopword_file = /path/to/custom_stopwords.txt

四、高级应用场景

1. 多字段加权搜索

可以为不同字段设置不同的权重:

-- 标题匹配的权重是内容的2倍
SELECT id, title, 
       MATCH(title) AGAINST('数据库')*2 + 
       MATCH(content) AGAINST('数据库') AS relevance
FROM articles
WHERE MATCH(title, content) AGAINST('数据库')
ORDER BY relevance DESC;

2. 同义词扩展

虽然MySQL不直接支持同义词,但可以通过应用层实现:

-- 搜索"电脑"时也匹配"计算机"
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('电脑 计算机' IN BOOLEAN MODE);

3. 搜索结果高亮

虽然MySQL不直接支持结果高亮,但可以通过应用层处理:

-- 获取匹配位置信息
SELECT 
    id,
    title,
    content,
    MATCH(title, content) AGAINST('数据库') AS score,
    SUBSTRING(content, 1, 100) AS snippet
FROM articles
WHERE MATCH(title, content) AGAINST('数据库')
LIMIT 10;

五、技术优缺点分析

优点:

  1. 内置支持,无需额外组件
  2. 与MySQL其他功能无缝集成
  3. 支持事务和ACID特性
  4. 配置简单,维护成本低

缺点:

  1. 性能不如专用搜索引擎(如Elasticsearch)
  2. 中文分词支持有限
  3. 大数据量时索引重建耗时
  4. 功能相对简单,缺少高级特性

六、注意事项

  1. 中文分词问题:MySQL的全文检索对中文支持有限,建议考虑使用ngram分词插件
  2. 索引大小:全文索引可能占用大量存储空间
  3. 实时性:新增记录不会立即出现在搜索结果中
  4. 最小词长度:默认忽略少于4个字符的词,可通过ft_min_word_len调整

七、总结

MySQL的全文检索功能为中小型应用提供了一个简单高效的文本搜索解决方案。虽然它在功能和性能上不如专用搜索引擎强大,但对于大多数常规需求已经足够。在实际应用中,建议:

  1. 合理设计索引结构
  2. 优化查询语句
  3. 监控性能指标
  4. 根据业务规模适时考虑迁移到专用搜索引擎

对于数据量不大、实时性要求不高的应用场景,MySQL全文检索仍然是一个性价比很高的选择。