前言
从MySQL5.6版本开始支持InnoDB引擎的全文索引,语法层面上大多数兼容之前MyISAM的全文索引模式。所谓全文索引,是一种通过建立倒排索引,快速匹配文档的方式。MySQL支持三种模式的全文检索模式:
- 自然语言模式(IN NATURAL LANGUAGE MODE),即通过MATCH AGAINST 传递某个特定的字符串来进行检索。
布尔模式(IN BOOLEAN MODE),可以为检索的字符串增加操作符,例如“+”表示必须包含,“-”表示不包含,“*”表示通配符(这种情况, 即使传递的字符串较小或出现在停词中,也不会被过滤掉),其他还有很多特殊的布尔操作符,可以通过如下参数控制:
mysql> show variables like '%ft_boolean_syntax%'; +-------------------+----------------+ | Variable_name | Value | +-------------------+----------------+ | ft_boolean_syntax | + -><()~*:""&| | +-------------------+----------------+ 1 row in set (0.00 sec)
复制- 查询扩展模式(WITH QUERY EXPANSION), 这种模式是自然语言模式下的一个变种,会执行两次检索,第一次使用给定的短语进行检索,第二次是结合第一次相关性比较高的行进行检索。
目前MySQL支持在CHAR、VARCHAR、TEXT类型的列上定义全文索引。
本文只是简单的分析了全文索引涉及到的代码模块以及5.7的一些新特性,源码部分基于MySQL5.7.8-rc版本,更细节的部分并未深入。
创建全文索引
如下例所示,一个简单的创建带全文索引表的SQL:
create table t1 (a int auto_increment primary key, b text, fulltext(b));
复制
磁盘上会产生多个文件:
$ls -lh /u01/my57/data/test/ total 1.3M FTS_000000000000010b_0000000000000154_INDEX_1.ibd FTS_000000000000010b_0000000000000154_INDEX_2.ibd FTS_000000000000010b_0000000000000154_INDEX_3.ibd FTS_000000000000010b_0000000000000154_INDEX_4.ibd FTS_000000000000010b_0000000000000154_INDEX_5.ibd FTS_000000000000010b_0000000000000154_INDEX_6.ibd FTS_000000000000010b_BEING_DELETED_CACHE.ibd FTS_000000000000010b_BEING_DELETED.ibd FTS_000000000000010b_CONFIG.ibd FTS_000000000000010b_DELETED_CACHE.ibd FTS_000000000000010b_DELETED.ibd t1.frm t1.ibd
复制
除了t1.frm和t1.ibd外,共分为以下几类表
FTS_000000000000010b_0000000000000154_INDEX_1~6.ibd这6个文件用于存储倒排索引,存储的是分词和位置以及document ID,根据分词的第一个字符值进行分区,映射到不同的文件中; 文件的命名规则为FTS_{TABLE_ID}_{INDEX_ID}_INDEX_{N}.ibd
FTS_000000000000010b_DELETED.ibd 包含已经被删除的DOC_ID,但还没从全文索引数据中删掉; FTS_000000000000010b_DELETED_CACHE.ibd 是前者的内存缓存(但是搜索了下代码,只有当
fts_cache_t::deleted_doc_ids
被使用时,才会在sync时转储到该表中,但并没有发现任何地方使用这个对象)FTS_000000000000010b_BEING_DELETED_CACHE.ibd 和 FTS_000000000000010b_BEING_DELETED.ibd,包含了已经被删除索引记录并且正在从全文索引中移除的DOC ID,前者是后者的内存版本,这两个表主要用于辅助进行OPTIMIZE TABLE时将DELETED/DELETED_CACHED表中的记录转储到其中。
FTS_000000000000010b_CONFIG.ibd,包含全文索引的内部信息,最重要的存储是FTS_SYNCED_DOC_ID,表示已经解析并刷到磁盘的doc id, 在崩溃恢复时,可以根据这个值判断哪些该重新解析并加入到索引cache中。
建全文索引辅助表函数参考:
ha_innobase::create |--> create_table_info_t::create_table |--> fts_create_common_tables
复制
当对一个已经存在的表上创建全文索引时,InnoDB采用了fork多个线程进行并发构建全文索引项的方法,并发度由参数 innodb_ft_sort_pll_degree
控制。因此在restore一个全文索引表时,我们建议先建表、导入数据,再在表上创建全文索引。
参考函数:row_merge_read_clustered_index --> row_fts_start_psort
线程回调函数为fts_parallel_tokenization
。
当表上存在全文索引时,就会隐式的建立一个名为FTS_DOC_ID的列,并在其上创建一个唯一索引,用于标识分词出现的记录行。你也可以显式的创建一个名为FTS_DOC_ID的列,但需要和隐式创建的列类型保持一致。
为了维护表上的全文索引信息,全文索引模块定义了大量的类来进行管理,总的来说如下图所示: