MySQL版本 5.7.29
数据库名 test
创建一个article表,仅包含两个字段,一个主键ID,一个是TEXT类型的body
create table article(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
body TEXT,
PRIMARY KEY(id));
mysql> select * from article;
+----+--------------------------------+
| id | body |
+----+--------------------------------+
| 1 | hello world, I am jack |
| 2 | What a good day, are you happy |
| 3 | nine years old |
| 4 | I like you very much |
| 5 | some one like yout not me |
+----+--------------------------------+
5 rows in set (0.00 sec)
create FULLTEXT INDEX ft ON article(body);
mysql> set global innodb_ft_table = 'test/article';
mysql> select * from information_schema.INNODB_FT_INDEX_TABLE;
+-------+--------------+-------------+-----------+--------+----------+
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+-------+--------------+-------------+-----------+--------+----------+
| day | 4 | 4 | 1 | 4 | 12 |
| good | 4 | 4 | 1 | 4 | 7 |
| happy | 4 | 4 | 1 | 4 | 25 |
| hello | 3 | 3 | 1 | 3 | 0 |
| jack | 3 | 3 | 1 | 3 | 18 |
| like | 6 | 7 | 2 | 6 | 2 |
| like | 6 | 7 | 2 | 7 | 9 |
| much | 6 | 6 | 1 | 6 | 16 |
| nine | 5 | 5 | 1 | 5 | 0 |
| not | 7 | 7 | 1 | 7 | 19 |
| old | 5 | 5 | 1 | 5 | 11 |
| one | 7 | 7 | 1 | 7 | 5 |
| some | 7 | 7 | 1 | 7 | 0 |
| very | 6 | 6 | 1 | 6 | 11 |
| world | 3 | 3 | 1 | 3 | 6 |
| years | 5 | 5 | 1 | 5 | 5 |
| you | 4 | 6 | 2 | 4 | 21 |
| you | 4 | 6 | 2 | 6 | 7 |
| yout | 7 | 7 | 1 | 7 | 14 |
+-------+--------------+-------------+-----------+--------+----------+
19 rows in set (0.01 sec)
记录了分词出现的文档ID、position,重复的分词会出现多行信息
假设我们要查询body
字段中带有ou
的信息
假设我们不用全文索引的方式查询,可以使用如下的语句
mysql> select * from article where body like '%ou%';
+----+--------------------------------+
| id | body |
+----+--------------------------------+
| 2 | What a good day, are you happy |
| 4 | I like you very much |
| 5 | some one like yout not me |
+----+--------------------------------+
3 rows in set (0.01 sec)
就算我们对body字段索引,这句话的查询也不会使用到索引
假设我们采用全文索引的方式查询,可以使用如下的语句
mysql> select * from article
mysql> where MATCH(body)
mysql> AGAINST('You' IN NATURAL LANGUAGEE MODE);
+----+--------------------------------+
| id | body |
+----+--------------------------------+
| 2 | What a good day, are you happy |
| 4 | I like you very much |
+----+--------------------------------+
2 rows in set (0.01 sec)
其表明的语义为 查询带有 you 这个word的body所在的行信息
在使用MATCH
函数进行全文检索的查询时,有四种模式,上面演示的是第一种模式IN NATURAL LANGUAGEE MODE
,这也是默认的模式,因此上面的语句,可以写为
select * from article where MATCH(body) AGAINST('You')
查看查询计划
mysql> EXPLAIN select * from article where MATCH(body) AGAINST('You');
+----+-------------+---------+------------+----------+---------------+------+---------+-------+------+----------+-------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+----------+---------------+------+---------+-------+------+----------+-------------------------------+
| 1 | SIMPLE | article | NULL | fulltext | ft | ft | 0 | const | 1 | 100.00 | Using where; Ft_hints: sorted |
+----+-------------+---------+------------+----------+---------------+------+---------+-------+------+----------+-------------------------------+
1 row in set, 1 warning (0.00 sec)
可以看到这句话使用了全文索引字段ft
进行了查询。