前言

在我们日常开发中,很多时候会遇到对数据库中某个字段模糊查询的需求,也就是like某个字段,但是很多公司像阿里,京东都禁止使用like来对数据库进行模糊查询,原因是啥呢?
我们先来看下面三条语句

其中title添加了索引

1.SELECT id,title from test_user where title like '张三%'
2.SELECT id,title from test_user where title like '%张三'
3.SELECT id,title from test_user where title like '%张三%'

上面三条语句只有第一条可能走索引,是否走索引还要看MySQL查询时索引的选择性问题,如果表中有十万条数据,title中含有张三的数据只有几百条时,索引的选择性很好,MySQL就会使用title索引,如果十万条数据中有九万九千条数据的title含有张三,那这次查询的索引选择性会非常差,就会走全表扫描,效率极其低下。
第二条和是第三条语句是一定不会走索引的,因为MySQL的索引是按照从前到后依次排列的。

方案1

可能这时候会想到新增一个专门用来做全文检索的工具,比如ElasticSearch,利用阿里的Canal中间件来订阅MySQL的binlog,将MySQL中的数据同步到ElasticSearch,但是如果之前没用ElasticSearch,只是只是对短文本全文检索而去新增ElasticSearch,显然有点得不偿失而且会增加开发和运维的成本,而且像ElasticSearch这种数据库也一定要保证高可用,就需要最少三台来组成一个高可用集群,而且通过订阅binlog的方式,也会影响数据的一致性,需要在架构和编码的过程中新增很多需要考虑的因素,所以要尽量简单方便的情况下实现全文检索,使用ElasticSearch并不是一个最好的方案。

方案2

这时候我们可以考虑一下用MySql5.7.6之后新增的全文解析器Ngram
ngram全文解析器适合对短文本来进行全文检索,如果是长文本或者大数据量的话ElasticSearch仍然是不可或缺的。

ngram的使用特点

  1. 可以支持中文、日文、韩文分词
  2. 只有char、varchar、text类型字段能创建全文索引
  3. 英文分词用空格,逗号;中文分词用 ngram_token_size 设定

ngram的检索方式

自然语言模式(NATURAL LANGUAGE MODE)

自然语言模式是MySQL 默认的全文检索模式。自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询

BOOLEAN模式(BOOLEAN MODE)

BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询

BOOLEAN的关键字

1.'dog cat'
字段当中加一个空格,表示查询结果中包含dog或者cat
2.'+dog +cat'
字段前面加'+',表示必须同时包含dog和cat
3.'+dog cat'
表示必须包含dog,对cat并不强制,如果出现cat,则相关性会更高
4.'+dog -cat'
表示必须包含dog,必须不包含cat
5.'+dog ~cat'
表示必须包含dog,对cat并不强制,如果出现cat,则相关性会变低
6.'+dog +(>cat <pig)'
表示必须包含dog和cat或者包含dog和pig,但是dog cat的相关性比dog pig的相关性高
7.'dog*'
表示包含以dog开头的内容

ngram的使用方法

  1. 添加全文索引

在这里插入图片描述
2. 查询

// 不指定模式,默认使用自然语言模式
SELECT * FROM articles WHERE MATCH (title) AGAINST ('文言文');
//使用 boolean mode通配符模式。
select * from articles where match(title) AGAINST('cal*' in boolean mode);
使用Boolean中 cal*的方式,查询以cal*开头的内容

默认自然语言模式不需要指定查询模式,而使用Boolean模式时需要指定
in boolean mode

ngram的配置相关参数

innodb_ft_min_token_size
默认3,表示最小3个字符作为一个关键词,增大该值可减少全文索引的大小
innodb_ft_max_token_size
默认84,表示最大84个字符作为一个关键词,限制该值可减少全文索引的大小
ngram_token_size
默认2,表示2个字符作为内置分词解析器的一个关键词,如对“abcd”建立全文索引,关键词为’ab’,‘bc’,‘cd’
当使用ngram分词解析器时,innodb_ft_min_token_size和innodb_ft_max_token_size 无效

如何设置ngram_token_size

第一种

mysqld --ngram_token_size=1

第二种

在配置文件中[mysqld]ngram_token_size=1

这三个参数均不可动态修改,修改了这些参数,需重启MySQL服务,并重新建立全文索引!!

结尾

MySQL的ngram的使用方式粗略介绍完了,在需要全文检索的情况下还是要取舍,如果是大数据,大文档的全文检索,改用ElasticSearch还是要用,如果是短文本的全文检索,就可以考虑一下Ngram,还是要根据实际的使用情况来决定,毕竟架构设计还是在于取舍,而不是一股脑的将所有东西都加进去。

谢谢观看,请关注点赞,感谢支持。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐