MySQL全文索引的理解与应用

背景

最近着手开发一个本地生活项目,其中,本人负责的模块之一是商品搜索。在设计过程中,研究了一些解决方案。其中,很多解决方式都倾向于采用ElasticSearch和分词器,但基于现有资源和开发时间等成本的估量,最终采用MySQL全文索引来实现。另外,这里也与我的一个开发理念有关,如果不能明确未来业务发展规模,则尽可能的采用简单的方式去开发,然后不断试错调整。

了解全文索引

从MySQL Version: 5.6开始,MySQL开始支持全文索引,它允许我们以一种类似正则匹配的方式,去匹配指定内容。关于全文索引,类型为 FULLTEXT ,只能使用于 InnoDBMyISAM 存储引擎,并且只能用于CHAR、VARCHAR和 TEXT类型的列。

创建方式

CREATE TABLE `goods_search` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key_word` varchar(250) DEFAULT NULL COMMENT '关键词',
  `goods_id` varchar(20) DEFAULT NULL COMMENT '商品id',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `full_goods_search` (`key_word`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

or

alter table goods_searchadd fulltext index full_goods_search(key_word);

or

CREATE FULLTEXT INDEX full_goods_search ON `t_member_goods_search` (`key_word`)

使用方式

MATCH (col1,col2,...) AGAINST (expr [search_modifier])
eg.SELECT * FROM goods_search WHERE MATCH(`key_word`) AGAINST('陈*' IN BOOLEAN MODE)

关于search_modifier有三种方式:

search_modifier:
  {
       IN NATURAL LANGUAGE MODE(默认)
     | IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION or WITH QUERY EXPANSION
     | IN BOOLEAN MODE
  }

IN NATURAL LANGUAGE MODE

对于该模式,官方文档的描述如下:

By default or with the IN NATURAL LANGUAGE MODE modifier, the MATCH() function performs a natural language search for a string against a text collection. A collection is a set of one or more columns included in a FULLTEXT index. The search string is given as the argument to AGAINST().

我的理解是,对于搜索的关键词,如下面的 “陈记顺和” ,它会将其进行分词,例如,分成 {陈记、记顺、顺和}(具体分词长度是可以设置的),然后对这个分词后的集合进行匹配,最终返回相关的数据。
在这里插入图片描述

IN BOOLEAN MODE

关于该模式,同样给出官方的定义:

MySQL can perform boolean full-text searches using the IN BOOLEAN MODE modifier. With this modifier, certain characters have special meaning at the beginning or end of words in the search string.

使用该模式的时候,不会像 NATURAL LANGUAGE MODE 那样分词搜索,然后返回相关的数据,它会以你输入的内容作为一个整体进行相关的匹配:
在这里插入图片描述
如上,如果采用 NATURAL LANGUAGE MODE 模式,搜索 “顺和人” 时,是可以正常返回结果的。但在IN BOOLEAN MODE 下不行。
在这里插入图片描述

WITH QUERY EXPANSION

Blind query expansion (also known as automatic relevance feedback) is enabled by adding WITH QUERY EXPANSION or IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION following the search phrase. It works by performing the search twice, where the search phrase for the second search is the original search phrase concatenated with the few most highly relevant documents from the first search.

关于该模式的理解,是在 IN NATURAL LANGUAGE MODE 模式下返回的结果下,进行一个二次的分词搜索。如官方文档描述,如果搜索的单词长度很短,通过该模式,可以尽可能的返回跟其有隐藏关系的数据。

在这里插入图片描述
如图,在IN NATURAL LANGUAGE MODE 模式下,只能返回id=1的数据,但在WITH QUERY EXPANSION 模式下,会返回两条数据。

参数

关于分词长度大小的设置,主要和这几个参数有关:
对于InnoDB引擎:

  • innodb_ft_max_word_len
  • innodb_ft_min_word_len

对于MyISAM引擎:

  • ft_max_word_len
  • ft_min_word_len

在这里插入图片描述

注意,如果使用ngram parser分词器创建全文索引,那么上面的参数设置会失效,得设置ngram_token_size ,其默认值为2。该分词器可以更好得支持中文。

The built-in MySQL full-text parser uses the white space between words as a delimiter to determine where words begin and end, which is a limitation when working with ideographic languages that do not use word delimiters. To address this limitation, MySQL provides an ngram full-text parser that supports Chinese, Japanese, and Korean (CJK). The ngram full-text parser is supported for use with InnoDB and MyISAM.

在这里插入图片描述

测试

造了50w的数据,测试下来,效果还是不错的,因为搜索时带上了分页,且索引的级别也都在const。但有个地方可以关注一下,就是搜索的字数越多 ,整体的时间花费会变得更多,这里可以视业务而定,在用户输入字数很长时,确据top N的字进行搜索。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

legendaryhaha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值