一、引言
演示说明
- 前面介绍过了,B+树索引的特点是可以通过索引字段的前缀进行查找。例如对于下面的查询B+树是支持的
select * from blog where content like 'xxx%';
- 但是有时候我们要查询的是博客的内容中含有“xxx”,而不是以“xxx”开头,所以应该是下面的SQL语句
select * from blog where content like '%xxx%';
- 因此上述SQL语句即便添加了B+树索引也是需要进行索引的扫描来得到结果
- 全文检索(Full-Text Search)是将存储于数据库中的整本书或整篇文章中的任意内容信息查找出来的技术。它可以根据需要获得全文中有关章、节、段、词等信息,也可以进行各种统计和分析
- MySQL全文检索历史发展:
- 在之前的MySQL数据库中,InnoDB不支持全文检索技术。,只有MyISAM存储引擎支持。大多数的用户转向MyISAM存储引擎,还可能需要进行表的拆分,并将需要进行全文检索的数据存储为MyISAM表。这样的确能够解决需求,但是却丧失了InnoDB存储引擎的事务性
- 从InnoDB 1.2.x版本开始,InnoDB开始支持全文检索,其支持MyISAM存储引擎的全部功能,并且还支持其他一些特性
二、倒排索引
- 全文检索通常使用倒排索引(inverted index)来实现。倒排索引同B树索引一样,也是一种索引结构
- 它在辅助表(auxiliary table)中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。这通常利用关键数组实现,其拥有两种表现形式:
- inverted file index:其表现形式为{单词,单词所在文档的ID}
- full inverted index:其表现形式为{单词,(单词所在文档的ID,在文档中的具体位置)}
- 例如下面是一张表t。其中有DocumentId、Text两个字段
①inverted file index
- 如果采用inverted file index的关联数组实现,则其存储的内容如下表所示,可以看到:
- 单词code存在于文档1和4中
- 单词days存在于文档3和6中
- 等等......
- 这样之后,进行全文查询就简单了:直接根据Documents得到包含查询关键字的文档
②full inverted index
- 如果采用full inverted index的关联数组实现,则其存储的内容如下表所示,可以看到:
- code单词为(1:6),(4,8):表示code这个单词出现在文档1的第6个单词处,和文档4的第8个单词处
- 等等......
- full inverted index还存储了单词所在的位置信息,所以其占用更多的空间,但是能更好地定位数据,并扩充一些其他的搜索特性
②full inverted index
- 如果采用full inverted index的关联数组实现,则其存储的内容如下表所示,可以看到:
- code单词为(1:6),(4,8):表示code这个单词出现在文档1的第6个单词处,和文档4的第8个单词处
- 等等......
- full inverted index还存储了单词所在的位置信息,所以其占用更多的空间,但是能更好地定位数据,并扩充一些其他的搜索特性
三、InnoDB全文检索的实现
- InnoDB从1.2.x开始支持全文检索的技术,其采用“full inverted index”的方式
- 在InnoDB存储引擎中,将(DocumentId,Position)视为一个“ilist”。因此在全文检索的表(辅助表,见下)中,有两个列:
- 一个是word字段。在word字段上有设有索引
- 另一个是ilist字段
- 此外,由于InnoDB存储引擎ilist字段中存放了Position信息,故可以进行Proximity Search,而MyISAM存储引擎不支持该特性
- 当前InnoDB的全文索引还存在以下的限制:
- 每张表只能有一个全文检索的索引
- 由多列组合而成的全文检索的索引列必须使用相同的字符集与排序规则
- 不支持没有单词界定符(delimiter)的语言,如中文、日语、韩语等
Auxiliary Table(辅助表)
- 正如前面所说的,倒排索引需要将word存放到一张表中,这个表称为Auxiliary Table(辅助表)
- 在InnoDB存储引擎中,为了提高全文检索的并行性能,共有6张Auxiliary Table,目前每张表根据word的Latin编码进行分区
- Auxiliary Table是持久的表,存放于磁盘上
innodb_ft_aux_table参数(辅助表的查看)
- InnoDB允许用户查看指定倒排索引的Auxiliary Table中分词的信息,可以通过这个参数来观察倒排索引的Auxiliary Table
- 例如下面的SQL语句设置查看test数据库下表fts_a的Auxiliary Table:
- 例如下面的SQL语句设置查看test数据库下表fts_a的Auxiliary Table:
set global innodb_ft_aux_table='test/fts_a';