MySQL优化系列4-全文索引
总结:
- 每张表只能有一个全文检索的索引
- 由多列组合而成的全文检索索引的列必须使用相同的字符集和排序规则
- MySQL 5.7.6之前只支持英文全文索引,因为是用空格作为分词条件
- MySQL 5.7.6之后利用内置ngram解析器分词,用来支持中文、日文、韩文分词。
- 查询条件中若存在全文索引,则走全文索引,mysql不会去对比哪个索引性能更高,例:...where match(content) against(‘high performance’) and author = 123;
- 允许在char、varchar、text类型上建立全文索引
- 全文索引不能跨表查询
- 如果要导入大数据集,则应该先导入数据再创建全文索引会更快
- 全文索引要全部缓存到内存中才能发挥最大性能,缓存默认大小为32m,通过参数innodb_ft_cache_size调整大小
- 全文索引是根据词频来查询的
mysql的全文索引局限性太多,非常不建议使用,老实用中间件吧
原理:
全文检索通常使用倒排索引实现,也是一种索引结构。它在辅助表(auxiliary table)中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。通常利用关联数组实现,有两种表现形式:
inverted file index {word,documentId}
full inverted index {word,(documentId,position)}
innodb采用full inverted index方式,在innodb中将(documentId,position)视为一个ilist.因此在全文检索的表中,有两个列,一列是word字段,另一个是ilist字段,并且在word字段上设有索引,因为在ilist字段上存放了position信息,所以支持邻近搜索(proximity search),myisam不支持。
存放索引信息的表为辅助表(Auxiliary Table),一共有6张,会持久化到磁盘中。Innodb中全文索引会在事务提交时先被保存在FTS Index Cache(红黑树结构)中,然后再异步批量同步到Auxiliary Table中
通过命令
set global innodb_ft_aux_table='数据库名/表名';
设置查看分词信息,设置后可以在information_schema.INNODB_FT_INDEX_TABLE中查看分词信息
在innodb中必须有一列名为FTS_DOS_ID且必须是BIGINT UNSIGNED NOT NULL与word进行映射,innodb会隐式的创建该列,且会在该列上创建一个名为FTS_DOC_ID_INDEX的唯一索引,也可以显示的手动创建
删除数据时,只删除FTS Index Cache中的记录,辅助表数据会被移动到INNODB_FT_BEING_DELETED并不会删除,所以在数据删除了过多的时候需要用
optimize table 优化全文索引,该命令通过参数innodb_ft_num_word_optimize来限制每次实际删除的分词数量,默认2000
停词表(stopword)
保存不需要进行分词的word,默认分词表information_schema.INNODB_FT_DEFAULT_STOPWORD
也可以指定自定义的分词表:
set global innodb_ft_server_stopword_table = "自定义分词表"
使用全文索引查询
MATCH(col1,col2,...) against (expr [search_modifier])
search_modifier:{
in natural language mode |
in natural language mode with query expansion |
in boolean mode |
with query expansion
}