MySql全文索引+Ngram

一、关于Ngram

1.1 什么是ngram

MySQL 内置的全文解析器使用单词之间的空格作为分隔符,这对于不使用空格做分隔符的语言是一种限制。为了解决这一限制,MySQL提供了一个支持中文、日文和韩文(CJK)的ngram全文解析器。ngram 全文解析器支持InnoDB和MyISAM的全文索引 。

ngram解析器将文本序列分词为连续的n个字符。例如,你可以使用ngram全文解析器为"早上好呀"进行不同值的n分词。

n=1: '早', '上', '好', '呀'

n=2: '早上', '上好', '好呀'

n=3: '早上好', '上好呀'

n=4: '早上好呀'

1.2 查看ngram配置

分词的实现是通过mysql的ngram_token_size这项配置实现的,可以执行如下语句查看ngram_token_size的配置

SHOW VARIABLES LIKE '%token%';

  • 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 无效

1.3 ngram检索模式

查询模式分为自然语言模式和布尔模式

自然语言模式(NATURAL LANGUAGE MODE)

  • 自然语言模式是MySQL 默认的全文检索模式。自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询。
  • 在自然语言模式(NATURAL LANGUAGE MODE)下,文本的查询被转换为n-gram分词查询的并集,比如查询地址中包含"太湖"的数据,那么返回的数据是地址字段中有"太"或者"湖"的数据集

布尔模式(BOOLEAN MODE)

  • BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询
  1. 为检索的字符串增加操作符,如"+"表示必须包含,"-"不包含,"*" 表示通配符,字符串较小或出现在停词中,也不会被过滤掉
  2. +word必须存在
  3. -word必须不存在
  4. (no operator)该word可选,如果出现relevance value更高
  5. distance 仅用于InnoDB表。查询多个单词之间的距离是否在distance(字节)内
  6. > < 分别表示出现该word时增加和降低relevance value
  7. ~ 出现该word时relevance value变负值,用于制造噪音词("noise" word)
  8. 表示以该字符串开头的word,写在word前不生效,word*才有效
  9. '' '' 中的内容视作一个短语(整体)
  • 布尔模式(BOOLEAN MODE)文本查询被转化为n-gram分词的短语查询,比如查询地址中包含"太湖"的数据,那么返回的数据是地址字段中有"太湖"的数据集
1.4 ngram查询关键词

ngram查询用MATCH() ... AGAINST 方式来进行搜索,并且查询的字段一定要设置ngram的全文索引,否则查询报错

MATCH():表示搜索的是那个列

AGAINST:表示要搜索的是那个字符串

查询订单表中收货地址中包含"太湖"的查询示例:select * from orders where MATCH(`UserAddress`) AGAINST('太湖' IN BOOLEAN MODE)

二、全文索引+Ngram配置

2.1 修改Ngram配置

修改ngram_token_size的方式有两种

1)使用命令:mysqld --ngram_token_size=1

2)在数据库配置文件 my.ini,在mysqld 下添加对ngram_token_size的配置:

ngram 配置

ngram_token_size=1

修改后,重启Mysql服务,使得配置生效

2.2 添加全文索引

全文索引只能在类型为 CHAR、VARCHAR 或者 TEXT 的字段上创建

比如对b_patient表中的CurrenAddress字段添加索引为例:

1、创建表的同时创建全文索引

CREATE TABLE b_patient(

Id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,

PatientName VARCHAR (200),

CurrentAddress VARCHAR (500),

建立全文索引,同时使用ngram全文分析器

FULLTEXT (CurrentAddress) WITH PARSER ngram

) ENGINE = INNODB;

2、通过 alter table 的方式来添加

ALTER TABLE b_patient ADD fulltext index full_index_address(CurrentAddress) WITH PARSER ngram;

3、直接通过create index的方式

CREATE FULLTEXT INDEX full_index_address ON b_patient(CurrentAddress) WITH PARSER `ngram`;

三、检索测试

自然语言模式

select PatientName,CurrentAddress from b_patient

where MATCH(`CurrentAddress`) AGAINST('五星' IN BOOLEAN MODE);

布尔模式

select PatientName,CurrentAddress from b_patient

where MATCH(`CurrentAddress`) AGAINST('太湖' IN BOOLEAN MODE);

相关推荐
heartbeat..2 小时前
Spring AOP 全面详解(通俗易懂 + 核心知识点 + 完整案例)
java·数据库·spring·aop
麦聪聊数据4 小时前
MySQL并发与锁:从“防止超卖”到排查“死锁”
数据库·sql·mysql
AC赳赳老秦5 小时前
DeepSeek 私有化部署避坑指南:敏感数据本地化处理与合规性检测详解
大数据·开发语言·数据库·人工智能·自动化·php·deepseek
myzshare6 小时前
实战分享:我是如何用SSM框架开发出一个完整项目的
java·mysql·spring cloud·微信小程序
YMatrix 官方技术社区6 小时前
YMatrix 存储引擎解密:MARS3 存储引擎如何超越传统行存、列存实现“时序+分析“场景性能大幅提升?
开发语言·数据库·时序数据库·数据库架构·智慧工厂·存储引擎·ymatrix
辞砚技术录7 小时前
MySQL面试题——索引2nd
数据库·mysql·面试
linweidong7 小时前
C++thread pool(线程池)设计应关注哪些扩展性问题?
java·数据库·c++
墨笔之风8 小时前
java后端根据双数据源进行不同的接口查询
java·开发语言·mysql·postgres
欧亚学术8 小时前
突发!刚刚新增17本期刊被剔除!
数据库·论文·sci·期刊·博士·scopus·发表
黑白极客8 小时前
怎么给字符串字段加索引?日志系统 一条更新语句是怎么执行的
java·数据库·sql·mysql·引擎