InnoDB全文索引是如何实现的?

分析&回答

全文索引的底层实现为倒排索引。

为什么叫倒排索引(反向索引)

当表上存在全文索引时,就会隐式的建立一个名为FTS_DOC_ID的列,并在其上创建一个唯一索引,用于标识分词出现的记录行。你也可以显式的创建一个名为FTS_DOC_ID的列,但需要和隐式创建的列类型保持一致,否则创建的时候将会报错,并且不能通过FTS_DOC_ID来查找列:

mysql> select * from articles where FTS_DOC_ID = 1;
ERROR 1054 (42S22): Unknown column 'FTS_DOC_ID' in 'where clause'
复制代码

所以建立的articles表中列为 FTS_DOC_ID、id、title、body
常规的索引是文档到关键词的映射:文档——>关键词
倒排索引是关键词到文档的映射:关键词——>文档
全文索引通过关键字找到关键字所在文档,可以提高查询效率

倒排索引结构

Number Text Documents
1 code (1:6),(4:8)
2 days (3:2),(6:2)
3 hot (1:3),(4:4)

是word + ilist的存储结构
Text对应于word,是一个分词。Document存储的是键值对,键为FTS_DOC_ID,值为在文档中的位置,对应于ilist。其中word保存在Auxiliary Table中,总共有六张,每张表根据word的Latin编码进行分区,下面有介绍。

FTS Index Cache(全文检索索引缓存)

  • 在事务提交的时候将分词写入到FTS Index Cache中
  • 批量更新到Auxiliary Table,为了提高性能不会插入一条数据立刻更新到Auxiliary Table。进行批量更新的几种情况:
    1. 全文检索索引缓存已满,默认大小为32M,可以通过修改innodb_ft_cache_size来改变FTS Index Cache的大小
    2. 关闭数据库的时候,将FTS Index Cache中的数据库会同步到磁盘上的Auxiliary Table中
    3. 当对全文检索进行查询时,首先会将在FTS Index Cache中对应的字段合并到Auxiliary Table中,然后在进行查询
    4. 当数据库突然宕机时,可能会导致一些FTS Index Cache中的数据未同步到Auxiliary Table上。数据库重启时,当用户对表进行全文检索时,InnoDB存储引擎会自动读取未完成的文档,然后进行分词操作,在将分词的结果放入到FTS Index Cache中。innodb_ft_cache_size的大小会影响恢复的时间
  • FTS Index Cache为红黑树结构,会根据(word,ilist)进行排序插入

Auxiliary Table(辅助表)

  • Auxiliary Table存储在磁盘中,进入保存mysql数据的目录下(xxx/xxx/data/study) 看到有FTS_000000000000005e_0000000000000087_INDEX_0~6.ibd,其对应的就是六张Auxiliary Table
    其余文件介绍:
FTS_000000000000005e_DELETED.ibd
FTS_000000000000005e_DELETED_CACHE.ibd 
复制代码

记录的是从Auxiliary Table中删除的FTS_DOC_ID,后者是前者的内存缓存

FTS_000000000000005e_BEING_DELETED.ibd 
FTS_000000000000005e_BEING_DELETED_CACHE.ibd 
复制代码

记录的是已经被删除索引记录并真正从FTS Index Cache删除的FTS_DOC_ID(即删除FTS Index Cache并做了OPTIMIZE TABLE),后者是前者的内存缓存。这两个表主要用于辅助进行OPTIMIZE TABLE时将DELETED/DELETED_CACHED表中的记录转储到其中

FTS_000000000000005e_CONFIG.ibd
复制代码

包含全文索引的内部信息,最重要的存储是FTS_SYNCED_DOC_ID,表示已经解析并刷到磁盘的FTS_DOC_ID, 在系统宕机时,可以根据这个值判断哪些该重新分词并加入到FTS Index Cache中

DML操作

DML 只是对表内部的数据操作,不涉及表的定义,结构的修改。 主要包括(insert)(delete)(update)(select) 删除数据库。

  • 插入操作
    插入操作较为简单,当往表中插入记录时,提交事务时会对全文索引上的列进行分词存储到FTS Index Cache,最后在批量更新到Auxiliary Table中
  • 删除操作
    当提交删除数据的事务以后,不会删除Auxiliary Table中的数据,而只会删除FTS Index Cache中的数据。对于Auxiliary Table中被删除的记录,InnoDB存储引擎会记录其FTS Document Id,并将其保存在DELETED Auxiliary Table中。可以通过OPTIMIZE TABLE手动删除索引中的记录。
  • 更新操作
  • 查找操作
    分为两步。第一步:根据检索词搜集符合条件的FTS_DOC_ID,在搜集满足条件的FTS_DOC_ID首先读取delete表中记录的FTS_DOC_ID,这些FTS_DOC_ID随后被用做过滤
    第二步:根据FTS_DOC_ID找到对应的记录,找到的记录是根据相关性大小降序返回的。

反思&扩展

说说正向索引和反向索引?

正向索引(forward index)

一般是通过key,去找value。

InnoDB全文索引是如何实现的?_第1张图片

反向索引(inverted index)

从词的关键字,去找文档。

InnoDB全文索引是如何实现的?_第2张图片

喵呜面试助手:一站式解决面试问题,你可以搜索微信小程序 [喵呜面试助手] 或关注 [喵呜刷题] -> 面试助手 免费刷题。如有好的面试知识或技巧期待您的共享!

你可能感兴趣的:(MySQL数据库,全文检索,数据库,搜索引擎)