MySQL全文索引使用教程

silverwq
2023-09-07 / 0 评论 / 321 阅读 / 正在检测是否收录...

概述

全文索引与普通的索引不是一回事,在查找上方面其效率是普通模糊(like)查询的 N 倍,是 MySQL 专门提供用作搜索引擎的。

Mysql 5.6 之前版本,只有 MyISAM 支持全文索引,5.6 之后,Innodb 和 MyISAM 均支持全文索引,另外,只有字段的数据类型为 char、varchar、text 才可以建全文索引。

5.6 之后 MySQL 自带 ngram 解析器,可以解析中日韩三国文字,如果不使用 ngram 解析器,则 MySQL 默认使用空格符号作为分隔符(对于英文自然够用了,但对于中日韩文字就不好用了,所以才需要 ngram 解析器)

创建索引

有两种方式:

一种是带有 ngram 解析器,会自动分词

ALTER TABLE news ADD FULLTEXT idx_full_text (`content`) WITH PARSER ngram;

另外一种是不带有 ngram 解析器的,以符号和空格分词

ALTER TABLE news ADD FULLTEXT idx_full_text (`content`);

查询

全文索引有专用的查询语法:match (字段) against (关键字),例如

select * from answer where match(content) against("测试表")

为了更好的搜索效果,通常会配置最小搜索长度。

全文索引的相关参数都无法进行动态修改,必须通过修改 MySQL 的配置文件来完成。

// MyISAM 全文索引的的分词
ft_min_word_len = 4; 默认值
ft_max_word_len = 84; 默认值

// InnoDB 全文索引的的分词
innodb_ft_min_token_size = 3; 默认值
innodb_ft_max_token_size = 84; 默认值

// ngram解析器令牌长度----即against()中字符串切分的最小字符长度,搜索语句的内容如果不是""起来,会被分词
ngram_token_size = 2~10 ; 默认值

通常修改最小搜索长度的值为 2,在 my.ini,的 [mysqld] 的下面追加以下内容:

[mysqld]
innodb_ft_min_token_size = 2
ft_min_word_len = 2
ngram_token_size = 2

查看变量值

show variables like "%ft%"

三种全文搜索模式

自然语言模式

IN NATURAL LANGUAGE MODE,默认情况下为该模式,例:

-- 如果最小搜索长度ngram_token_size为1的话,则查找包含张,或三,或张三的记录;与布尔搜索模式中的‘+张三’结果相同
SELECT * FROM user WHERE MATCH(userName) AGAINST (‘张三’ );

布尔搜索模式

有以下几个操作符:

  1. 【+】----------必须包含此字符串
  2. 【-】----------必须不包含此字符串
  3. 【""】--------双引号内作为整体不能拆词
  4. 【>】--------提高该词的相关性,查询的结果靠前
  5. 【<】--------降低该词的相关性,查询的结果靠后
  6. *】---------通配符,只能接在词后面

例如,查询有"美女"的又有"动人"的记录:

SELECT * FROM user WHERE MATCH(userName) AGAINST ('+"美女" & +"动人"' IN BOOLEAN MODE);

查询扩展搜索

较少使用,没有细了解

多字段索引

对 title 和 body 字段建立索引

ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram;

然后 selec 语句如下使用即可:

SELECT 
  id,
  title,
  body,
  MATCH (title,body) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score
FROM 
  articles 
where 
  MATCH (title,body) AGAINST ('标题' IN NATURAL LANGUAGE MODE)
ORDER BY score DESC;

不过上面这种方式,两个字段的权重是一样,有时候希望不同字段的权重不一样,例如希望你 title 字段权重大一点,这个只需要分别对字段建立索引,然后改下排序方式即可满足,例如:

SELECT 
  id,
  title,
  body,
  MATCH (title) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score_title,
  MATCH (body) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score_body
FROM 
  articles 
where 
  (MATCH (title) AGAINST ('标题' IN NATURAL LANGUAGE MODE) OR MATCH (body) AGAINST ('标题' IN NATURAL LANGUAGE MODE))
-- 主要是改排序方式
ORDER BY score_title DESC,score_body DESC;
0

评论 (0)

取消