前言

在实际的开发中,我们常常会遇到模糊查询的需求。比如在电商网站里搜索商品,想找“耐克运动鞋”,可能就会在搜索框里输入关键词,后台需要从大量的商品信息里找出包含这些关键词的商品。但传统的模糊查询在数据量特别大的时候,性能就会变得很差,速度慢得让人着急。今儿咱就来聊聊怎么用 MySQL 全文检索来解决这个模糊查询性能的大难题。

一、什么是模糊查询和 MySQL 全文检索

模糊查询

模糊查询就是在数据库里查找那些不完全匹配我们输入内容的数据。就好比你在图书馆找书,只记得书的名字里有“历史”两个字,这时候你就可以通过模糊查询在图书馆的书目系统里找出所有书名包含“历史”的书。在 MySQL 里,常用的模糊查询是用 LIKE 关键字。

示例(MySQL 技术栈):

-- 从 products 表中查找商品名称包含 '手机' 的记录
SELECT * FROM products WHERE product_name LIKE '%手机%';
-- '%' 是通配符,表示可以匹配任意数量的任意字符

MySQL 全文检索

MySQL 全文检索是一种更强大的搜索功能,它专门用来处理文本搜索。它会对文本内容进行分词处理,建立索引,这样在搜索的时候就能更高效地找到包含关键词的记录。还是拿图书馆举例,全文检索就像是图书馆给每本书的内容都做了详细的索引,你只要输入相关的关键词,就能快速定位到包含这些关键词的书的位置。

二、模糊查询的性能问题

问题表现

当数据库里的数据量很大的时候,模糊查询的性能就会变得特别糟糕。比如一个电商网站有几百万条商品记录,你用 LIKE 进行模糊查询,服务器可能要花很长时间才能把结果返回给你,用户体验就会很差。

原因分析

LIKE 查询在执行的时候,数据库需要对每一行数据进行匹配,不管是前面加 % 还是后面加 %,都没办法利用索引,只能进行全表扫描。全表扫描就相当于你在图书馆里一本一本挨着找书,数据量越大,找起来就越慢。

示例(MySQL 技术栈):

-- 假设 products 表有 100 万条记录
-- 这个查询会进行全表扫描
SELECT * FROM products WHERE product_name LIKE '%智能%';

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

1. 创建全文索引

首先,我们要在需要进行全文检索的字段上创建全文索引。就像在图书馆给书做索引一样,有了索引,查找起来就快多了。

示例(MySQL 技术栈):

-- 在 products 表的 product_name 字段上创建全文索引
CREATE FULLTEXT INDEX idx_product_name ON products (product_name);

2. 使用 MATCH AGAINST 进行查询

创建好全文索引后,我们就可以用 MATCH AGAINST 语句来进行全文检索了。

示例(MySQL 技术栈):

-- 从 products 表中查找商品名称包含 '智能' 的记录
SELECT * FROM products WHERE MATCH(product_name) AGAINST('智能' IN NATURAL LANGUAGE MODE);
-- IN NATURAL LANGUAGE MODE 表示使用自然语言模式进行搜索

3. 不同搜索模式

自然语言模式

自然语言模式是最常用的模式,它会把查询的关键词当作自然语言中的词汇来处理,查找包含这些关键词的记录。

示例(MySQL 技术栈):

-- 查找商品描述中包含 '舒适' 的记录
SELECT * FROM products WHERE MATCH(product_description) AGAINST('舒适' IN NATURAL LANGUAGE MODE);

布尔模式

布尔模式允许我们使用一些逻辑运算符,比如 +(必须包含)、-(必须不包含)等,来更精确地控制搜索结果。

示例(MySQL 技术栈):

-- 查找商品名称中必须包含 '苹果' 且不能包含 '二手' 的记录
SELECT * FROM products WHERE MATCH(product_name) AGAINST('+苹果 -二手' IN BOOLEAN MODE);

四、应用场景

电商平台商品搜索

在电商平台上,用户会在搜索框里输入各种关键词来查找商品。比如用户想找“华为手机”,这时候用全文检索就能快速从大量的商品信息里找到符合条件的商品,提高搜索速度和用户体验。

示例(MySQL 技术栈):

-- 从商品表中查找商品名称包含 '华为手机' 的记录
SELECT * FROM products WHERE MATCH(product_name) AGAINST('华为手机' IN NATURAL LANGUAGE MODE);

新闻网站文章搜索

新闻网站有大量的文章,用户可能会根据关键词来搜索感兴趣的文章。全文检索可以帮助网站快速定位到包含关键词的文章,让用户更快地获取信息。

示例(MySQL 技术栈):

-- 从文章表中查找文章标题或内容包含 '科技新闻' 的记录
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('科技新闻' IN NATURAL LANGUAGE MODE);

五、技术优缺点

优点

性能提升

相比于传统的 LIKE 查询,全文检索在处理大量文本数据时,性能有显著的提升。因为它使用了索引,避免了全表扫描,查找速度更快。

功能强大

支持多种搜索模式,如自然语言模式和布尔模式,可以满足不同的搜索需求。

缺点

索引维护成本高

创建全文索引需要占用一定的磁盘空间,而且在数据更新、插入、删除时,索引也需要相应地更新,这会增加一定的系统开销。

中文分词问题

MySQL 自带的分词器对中文的支持不是很好,可能需要使用第三方的分词器来提高分词效果。

六、注意事项

索引更新

当数据库中的数据发生变化时,全文索引也需要更新。如果数据更新频繁,可能会影响系统的性能。可以考虑在业务低峰期进行数据更新操作,或者采用异步更新索引的方式。

最小搜索长度

MySQL 有一个最小搜索长度的限制,默认情况下,长度小于 4 个字符的单词会被忽略。如果需要搜索短词,可以通过修改配置文件来调整最小搜索长度。

示例(修改 MySQL 配置文件):

# 在 my.cnf 或 my.ini 文件中添加以下配置
ft_min_word_len = 2
# 重启 MySQL 服务使配置生效

中文分词

对于中文搜索,MySQL 自带的分词器可能无法满足需求。可以使用第三方的分词器,如盘古分词、结巴分词等,并将其集成到 MySQL 中。

七、文章总结

在实际的开发中,当我们遇到需要进行模糊查询,而且数据量较大时,传统的 LIKE 查询会带来严重的性能问题。这时候,MySQL 全文检索就是一个很好的解决方案。通过创建全文索引,使用 MATCH AGAINST 语句进行查询,我们可以显著提高搜索的性能。同时,全文检索还支持多种搜索模式,能够满足不同的搜索需求。

不过,在使用 MySQL 全文检索时,我们也需要注意一些问题,比如索引维护成本、中文分词等。要根据具体的业务场景和需求,权衡利弊,合理使用全文检索技术。