需要模糊匹配查询一个单词
select * from t_phrase where LOCATE('昌',phrase) = 0;
select * from t_chinese_phrase where instr(phrase,'昌') > 0;
select * from t_chinese_phrase where phrase like '%昌%'
explain一下看看执行计划

由explain的结果可知,虽然我们给phrase建了索引,但是查询的时候,索引是失效的。
原因: mysql的索引是B+树结构,InnoDB在模糊查询数据时使用 "%xx" 会导致索引失效(此处就不展开讲了)
从查询时长上来看,花费时间:90ms
目前数据量:93230(9.3W)已经需要90ms,这个时间不太能接受,假如数据量增加,这个时间会不断增长。
解决方案:
数据量不大的情况下,使用mysql的全文索引;
数据量比较大或者mysql的全文索引不达预期的情况下,可以考虑使用ES
下面主要是MySQL的全文索引相关.
1、发展历史
旧版的MySQL的全文索引只能用在MyISAM存储引擎的char、varchar和text的字段上。
MySQL5.6.24上InnoDB引擎也加入了全文索引。
2、全文索引
3、创建全文索引
若需对大量数据设置全文索引,建议先添加数据再创建索引。

IN BOOLEAN MODE
BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。推荐使用boolean模式
| 操作者 | 描述 |
|---|---|
| 为空 | 默认,包含该词 |
| + | 包括,这个词必须存在。 |
| – | 排除,词不得出现。 |
| >(大于号) | 包括,并提高排名值,查询的结果会靠前 |
| < | 包括,并降低排名值,查询的结果会靠后 |
| () | 将单词分组为子表达式(允许将它们作为一组包括在内,排除在外,排名等等)。 |
| 〜 | 否定单词的排名值。 |
| * | 通配符在这个词的结尾。 |
| “” | 定义短语(与单个单词列表相对,整个短语匹配以包含或排除)。 |
示例:


好像问题都解决了, 但是问题才刚开始
回到最开始的需求,我想模糊搜索

全匹配查询的时候能查询出来

只查询部分查询不出来。如:下面只查询 "小水" 或者"水牛" 都没有数据

奇怪了,这咋没出来呢?
全文索引默认是只按照空格进行分词的,所以当我完整的单个单词去查询的时候是能查出来的。但是使用部分单词去查询或者使用部分中文去查询时,是查询不出来数据的,像中文需要使用中文分词器进行分词。
InnoDB默认的全文索引parser非常合适于Latin,因为Latin是通过空格来分词的。但对于像中文,日文和韩文来说,没有这样的分隔符。一个词可以由多个字来组成,所以我们需要用不同的方式来处理。在MySQL 5.7.6中我们能使用一个新的全文索引插件来处理它们:N-gram parser。
在全文索引中,n-gram就是一段文字里面连续的n个字的序列。例如,用n-gram来对“齿轮传动”来进行分词,得到的结果如下:

参数解析:
innodb_ft_min_token_size默认3,表示最小3个字符作为一个关键词,增大该值可减少全文索引的大小
innodb_ft_max_token_size默认84,表示最大84个字符作为一个关键词,限制该值可减少全文索引的大小
ngram_token_size默认2,表示2个字符作为内置分词解析器的一个关键词,合法取值范围是1-10,如对“abcd”建立全文索引,关键词为’ab’,‘bc’,‘cd’ 当使用ngram分词解析器时,innodb_ft_min_token_size和innodb_ft_max_token_size 无效
方式1: 在my.cnf中修改/添加参数

因为我们上面设置了分词数是1,所以,可以看到都是按照一个词进行分词的。
字段解析:
FIRST_DOC_ID :word第一次出现的文档ID
LAST_DOC_ID : word最后一次出现的文档ID
DOC_COUNT :含有word的文档个数
DOC_ID :当前文档ID
POSITION : word 当在前文档ID的位置
在自然语言模式(NATURAL LANGUAGE MODE)下,文本的查询被转换为n-gram分词查询的并集。
例如,当ngram_token_size = 1 时,(‘繁荣昌盛’)转换为(‘繁 荣 昌 盛’)。
下面一个例子:

布尔模式(BOOLEAN MODE)文本查询被转化为n-gram分词的短语查询
例如,当ngram_token_size = 1 时,(‘繁荣昌盛’)转换为(‘”繁荣昌盛“’)。下面一个例子:

回到我们最开始的查询需求,看看实际的效果
查询包含了“昌”的数据

可以看到结果:目前“昌”在任意位置都能被查询到。
查询执行计划如下:

耗时31ms(不走索引是90ms),耗时差不多是之前的1/3。
1、自然语言全文索引创建索引时的字段需与查询的字段保持一致,即MATCH里的字段必须和FULLTEXT里的一模一样;
2、自然语言检索时,检索的关键字在所有数据中不能超过50%(即常见词),则不会检索出结果。可以通过布尔检索查询;
3、在mysql的stopword中的单词检索不出结果。可通过
查询所有的stopword。遇到这种情况,有两种解决办法:
(1)stopword一般是mysql自建的,但可以通过设置ft_stopword_file变量为自定义文件,从而自己设置stopword,设置完成后需要重新创建索引。但不建议使用这种方法;
(2)使用布尔索引查询。
4、小于最短长度和大于最长长度的关键词无法查出结果。可以通过设置对应的变量来改变长度限制,修改后需要重新创建索引。
myisam引擎下对应的变量名为ft_min_word_len和ft_max_word_len
innodb引擎下对应的变量名为innodb_ft_min_token_size和innodb_ft_max_token_size
5、MySQL5.7.6之前的版本不支持中文,需使用第三方插件
6、全文索引只能在 InnoDB(MySQL 5.6以后) 或 MyISAM 的表上使用,并且只能用于创建 char,varchar,text 类型的列。
以上就是MySQL全文索引like模糊匹配查询慢解决方法的详细内容,更多关于MySQL索引like模糊查询慢的资料请关注其它相关文章!