MySQL如何使用全文索引

前言

全文索引通过建立倒排索引来快速匹配文档,mysql5.6版本以上innodb支持。
MySQL的全文索引支持以下3种查询语法:

  1. 自然语言模式(IN NATURAL LANGUAGE MODE)
    通过MATCH AGAINST 传递某个特定的字符串来进行检索
  2. 布尔模式(IN BOOLEAN MODE)
    支持操作符,例如+表示包含,-表示不包含
  3. 扩展模式(WITH QUERY EXPANSION)
    相当于自然语言模式下的一个扩展,执行两次检索,第一次使用给定短语检索,第二次是结合第一次相关性比较高的行进行检索.
    更多信息请查看官方文档

下面教大家如果创建全文索引,并创建测试数据演示三种查询模式的使用

一、如何创建全文索引

方式一:建表的时候指定

 CREATE TABLE table_name ( 
                  id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, 
                  title VARCHAR(200), 
                  content TEXT, 
                  FULLTEXT(title, content) 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ; 

方式二:通过ALTER添加

  ALTER TABLE table_name ADD FULLTEXT INDEX index_name (column1,column2,...);

方式三:直接使用CRATE INDEX语法

   CREATE FULLTEXT INDEX index_name ON table_name (column1,column2,...)

二、创建测试数据

创建一个数据库用来演示这三种模式下的检索

CREATE DATABASE chenqionghe DEFAULT CHARSET utf8;

创建一个文章表并插入测试数据

CREATE TABLE articles (
          id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
          title VARCHAR(200),
          body TEXT,
          FULLTEXT (title,body)
        ) ENGINE=InnoDB;

插入测试数据


INSERT INTO articles (title,body) VALUES
        ('MySQL Tutorial','DBMS stands for DataBase ...'),
        ('How To Use MySQL Well','After you went through a ...'),
        ('Optimizing MySQL','In this tutorial we will show ...'),
        ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
        ('MySQL vs. YourSQL','In the following database comparison ...'),
        ('MySQL Security','When configured properly, MySQL ...')

三、查询-使用自然语言模式

这是MySQL的默认查询模式。
查询示例如下

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body)
    -> AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

使用MATCH查询,返回的结果将以相关性进行排序相关性是根据行中的字段、唯一单词的数量、集合中单词总数和包含特定单词的行数计算。

# 第一种方式
 SELECT COUNT(*) FROM articles
    WHERE MATCH (title,body)
    AGAINST ('database' IN NATURAL LANGUAGE MODE);
# 第二种方式
SELECT
   COUNT(IF(MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))
    AS count
    FROM articles

第一种做了一些额外的工作(按相关性对结果进行排序),但也能使用索引进行查询。
第二种执行了全表扫描,如果搜索项出现在大多数行中,可能比索引查询更快
匹配少数行,第一种快,匹配大多数行,第二种快

下面的演示如何检索相关性,但是不会进行排序(因为不包含WHERE和ORDER BY)

mysql> SELECT id, MATCH (title,body)
    -> AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS score
    -> FROM articles;
+----+---------------------+
| id | score |
+----+---------------------+
| 1 | 0.22764469683170319 |
| 2 | 0 |
| 3 | 0.22764469683170319 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+---------------------+
6 rows in set (0.00 sec)

下面的示例更复杂,返回倒序后的相关性值,分别在SELECT和WHERE语句中使用了MATCH,但是不会导致额外的开销,因为mysql优化器注意到两次MATCH是相同的,只会使用一次全文搜索

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body)
    -> AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

mysql>
mysql> SELECT id, body, MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root'
    -> IN NATURAL LANGUAGE MODE) AS score
    -> FROM articles WHERE MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root'
    -> IN NATURAL LANGUAGE MODE);
+----+------------------------------------------+----------------------------+
| id | body | score |
+----+------------------------------------------+----------------------------+
| 4 | 1. Never run mysqld as root. 2. ... | 0.6055193543434143 |
| 6 | When configured properly, MySQL ... | 0.6055193543434143 |
| 1 | DBMS stands for DataBase ... | 0.000000001885928302414186 |
| 2 | After you went through a ... | 0.000000001885928302414186 |
| 3 | In this tutorial we will show ... | 0.000000001885928302414186 |
| 5 | In the following database comparison ... | 0.000000001885928302414186 |
+----+------------------------------------------+----------------------------+
6 rows in set (0.01 sec)

包含在("")字符中的我确认下会被分解为单词,并在全文索引中搜索。

全文索引将连续的(字母、数字和下划线)当做一个单词。
全文索引分割单词一般用空格/逗号/句号

四、查询-使用布尔模式

使用布尔模式需要指定IN BOOLEAN MODE,一些字符具有特殊的含义,例如可以通过+或-表示一个单词必须存在或不存在。
下面的sql语句代表查询必须 包含MySQL但不包含YourSQL

mysql> SELECT * FROM articles WHERE MATCH (title,body)
    -> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+
| id | title | body |
+----+-----------------------+-------------------------------------+
| 6 | MySQL Security | When configured properly, MySQL ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 2 | How To Use MySQL Well | After you went through a ... |
| 3 | Optimizing MySQL | In this tutorial we will show ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
+----+-----------------------+-------------------------------------+
5 rows in set (0.01 sec)

注意:

    • 代表 AND
    • 代表 NOT
  • [无字符]代表 OR

布尔模式有以下特点:

  1. 不会自动根据相关性排序
    支持以下操作符号:
    • 必须出现
    • 必须不出现。
      注意:这个操作符是用来排除其他操作符的结果,如果只指定这个,将什么都不返回
  • 无符号
    默认情况,代表或,自动分词搜索。和没有指定IN BOOLEAN MODE 的结果一样
  • @distance
    仅支持InnoDB。
    用来测试两个或两个以上的单词是否都在一个指定的距离内。
    在@距离前指定双引呈字符串中的搜索词,例如
 MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE)
  • > <
    用来提高或降低单词的相关性
  • ( )
    和们我表达式使用的括号一个功能,相当于表达式分组
  • ~
    将其相关性由正转负,表示拥有该字会降低相关性
    eg: +apple ~macintosh 先匹配apple,但如果同时包含macintosh,就排名会靠后。
    • 通配符,只能在字符串后面使用
  • "
    完全匹配,被双引号包起来的完全匹配

操作符使用示例

  • 'apple banana'
    搜索包含apple或banana其中一个
  • '+apple +juice'
    必须同时包含apple和juice
  • '+apple macintosh'
    包含apple,但是如果同时包含macintosh会给更高的排序
  • '+apple -macintosh'
    包信apple但是不包含macintosh
  • '+apple ~macintosh'
    包含apple,如果同时包含macintosh降低权重
  • '+apple +(>turnover <strudel)'
    1.包含apple和turnover,或,包含apple和strudel
    2.包含apple和turnover权重高于包含apple和strudel的记录
  • 'apple*'
    包含apple单词的行, “apple”, “apples”, “applesauce”, “applet”都会被匹配到
  • '"some words"'
    完全匹配·some words·的行,例如 “some words of wisdom”能匹配但 “some noise words”不匹配

五、查询-使用扩展模式

当搜索短语很短时,很有用,例如搜索database可能意味着MySQL、Oracle、DB2、RDBMS都要被匹配到,这就是这个模式能做的。
启用这个模式是在搜索词后面添加WITH QUERY EXPANSIONIN NATURAL LANGUAGE MODE WITH QUERY EXPANSION,它会执行两次检索,第一次使用给定短语检索,第二次是结合第一次相关性比较高的行进行检索。
例如下面的例子

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body)
    -> AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body)
    -> AGAINST ('database' WITH QUERY EXPANSION);
+----+-----------------------+------------------------------------------+
| id | title | body |
+----+-----------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 3 | Optimizing MySQL | In this tutorial we will show ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
| 2 | How To Use MySQL Well | After you went through a ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
+----+-----------------------+------------------------------------------+
6 rows in set (0.00 sec)

可以看到第二条语句找到了包含MySQL的行,即使该行不包含database,但是因为在第一次的搜索中搜索引擎判断MySQL和database的相关性比较高,所以在执第二次搜索的时候返回了。

六、注意事项

  1. 只能在类型为CHAR、VARCHAR或者TEXT的字段上创建全文索引2.
  2. 全文索引是以词为基础的,innodb_ft_min_token_size和innodb_ft_max_token_size 分别用来设置字符串的最大和最小值,不在这个长度内的将不被用来查询
  3. MATCH (字段) AGAINST (关键词),必须和创建时的字段一起,例如MATCH (light,weight,baby)使用的字段名与全文索引muscle(light,weight,baby)定义的字段名一致。如果只对单个字段查询,需要分别创建全文索引
  4. 在停用词stopwords中的将被忽略
  5. 如果要导入大量数据,先导入数据再建全文索引,比先建全文索引再导入数据的方式快很多。
  6. 在MySQL 5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,MySQL 5.7.6后内置了ngram全文解析器,支持中文、日文、韩文分词。

猜你喜欢

转载自www.cnblogs.com/chenqionghe/p/12364524.html