问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

innodb不支持全文索引,会不会很慢?

发布网友 发布时间:2022-04-08 19:34

我来回答

3个回答

懂视网 时间:2022-04-08 23:56

GLOBAL innodb_ft_aux_table=‘test/fts_a‘;

可以在information_schema架构下的表INNODB_FT_INDEX_TABLE得到表fts_a中的分词信息。

对于InnoDB存储引擎而言,其总是在事务提交时将分词写入到FTS Index Cache,然后通过批量写入到磁盘。虽然InnoDB存储引擎通过一种延时的、批量的写入方式来提高数据库的性能,但是上述操作仅在事务提交时发生。

当数据库关闭时,在FTS Index Cache中的数据库会同步到磁盘上的Auxiliary Table中。如果当数据库发生宕机时,一些FTS Index Cache中的数据可能未同步到磁盘上,那么下次重启数据库时,当用户对表进行全文检索(查询、插入)时,InnoDB存储引擎会自动读取未完成的文档,然后进行分词操作,再将分词结果放到FTS Index Cache

为了支持全文检索,必须有一个列与word进行映射。在InnoDB中这个列被命名成FTS_DOC_ID,其类型为BIGINT UNSIGNED NOT NULL,并且InnoDB存储引擎自动会在该列加上一个名为FTS_DOC_ID_INDEX的Unique Index.这些操作由存储引擎自己完成,用户也可以在建表时自动添加FTS_DOC_ID,以及对应的Unique Index。由于列名FTS_DOC_ID聚友特殊意义,因此在创建时必须注意相应的类型,否则会报错

技术分享

可以看到,由于用户手动定义FTS_DOC_ID为INT,而非BIGINT因此在创建时候会抛出异常,应该将此处修改成对应的BIGINT即可

文档中的分词的插入操作是在事务提交时完成,但是对于删除操作,其在事务提交时,不删除磁盘Auxiliary Table的记录,而只是删除FTS Cache Index记录,对于Auxiliary Table中被删除的记录,存储引擎会记录其FTS DOCUMENT ID ,并将其保存在DELETE auxiliary table中,在设置参数innodb_ft_aux_table后,用户可以访问information_schema架构下的表INNODB_FT_DELETED来观察删除的FTS Document ID

由于文档的DML操作实际并不删除索引中的数据,相反还会在对应的DELETED表中插入记录,因此随着应用程序的允许,索引会变得越来越大,即使索引中的有些数据已经被删除,查询也不会选择这类记录,为此,InnoDB提供了一种方式,允许用户手工将已删除的记录从索引中彻底删除,这就是OPTIMIZE TABLE。因为OPTIMIZE TABLE还会进行一些其他的操作。如Cardinality重新统计,若用户希望对倒排索引进行操作,可以通过innodb_optimize_fulltext_only设置

SET GLOBAL innodb_optimize_fulltext_only=1;

OPTIMIZE TABLE fts_a;

若被删除的文档很多,那么OPTIMIZE TABLE操作可能占用非常多的时间,会影响到程序并发性,并极大的降低用户的响应时间,用户可以通过参数innodb_ft_num_word_optimize来限制每次实际删除的分词数量,默认为2000

CREATE TABLE fts_a(
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
body TEXT,
PRIMARY KEY(FTS_DOC_ID)
);


INSERT INTO fts_a SELECT NULL,‘pease porridge in the post‘;
INSERT INTO fts_a SELECT NULL,‘pease porridge hot,pease porridge cold‘;
INSERT INTO fts_a SELECT NULL,‘Nine days old‘;
INSERT INTO fts_a SELECT NULL,‘Some like it hot,some like it cold‘;
INSERT INTO fts_a SELECT NULL,‘Some like it the pot‘;
INSERT INTO fts_a SELECT NULL,‘Nine days old‘;
INSERT INTO fts_a SELECT NULL,‘I like code days‘;

CREATE FULLTEXT INDEX idx_fts ON fts_a(body);

查看数据

mysql> select * from fts_a;
+------------+----------------------------------------+
| FTS_DOC_ID | body     |
+------------+----------------------------------------+
|  1 | pease porridge in the post  |
|  2 | pease porridge hot,pease porridge cold |
|  3 | Nine days old    |
|  4 | Some like it hot,some like it cold |
|  5 | Some like it the pot   |
|  6 | Nine days old    |
|  7 | I like code days   |
+------------+----------------------------------------+
7 rows in set (0.00 sec)
mysql> set global innodb_ft_aux_table=‘iot2/fts_a‘;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM information_schema.`INNODB_FT_INDEX_TABLE`;
+----------+--------------+-------------+-----------+--------+----------+
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+----------+--------------+-------------+-----------+--------+----------+
| code | 7 | 7 | 1 | 7 | 7 |
| cold | 2 | 4 | 2 | 2 | 34 |
| cold | 2 | 4 | 2 | 4 | 30 |
| days | 3 | 7 | 3 | 3 | 5 |
| days | 3 | 7 | 3 | 6 | 5 |
| days | 3 | 7 | 3 | 7 | 12 |
| hot | 2 | 4 | 2 | 2 | 15 |
| hot | 2 | 4 | 2 | 4 | 13 |
| like | 4 | 7 | 3 | 4 | 5 |
| like | 4 | 7 | 3 | 4 | 17 |
| like | 4 | 7 | 3 | 5 | 5 |
| like | 4 | 7 | 3 | 7 | 2 |
| nine | 3 | 6 | 2 | 3 | 0 |
| nine | 3 | 6 | 2 | 6 | 0 |
| old | 3 | 6 | 2 | 3 | 10 |
| old | 3 | 6 | 2 | 6 | 10 |
| pease | 1 | 2 | 2 | 1 | 0 |
| pease | 1 | 2 | 2 | 2 | 0 |
| pease | 1 | 2 | 2 | 2 | 19 |
| porridge | 1 | 2 | 2 | 1 | 6 |
| porridge | 1 | 2 | 2 | 2 | 6 |
| porridge | 1 | 2 | 2 | 2 | 19 |
| post | 1 | 1 | 1 | 1 | 22 |
| pot | 5 | 5 | 1 | 5 | 17 |
| some | 4 | 5 | 2 | 4 | 0 |
| some | 4 | 5 | 2 | 4 | 17 |
| some | 4 | 5 | 2 | 5 | 0 |
+----------+--------------+-------------+-----------+--------+----------+
27 rows in set (0.00 sec)

可以看到每个word对应一个DOC_ID和POSITION。此外,还记录了FIRST_DOC_ID、LAST_DOC_ID、DOC_COUNT分别代表该word第一次出现文档的ID,最后一次出现的文档ID,以及该word在多少个文档中存在。

若此时执行下面的SQL语句,会删除FTS_DOC_ID为7的文档

DELETE FROM fts_a WHERE FTS_DOC_ID=7;

InnoDB存储引擎并不会直接删除索引中对应的记录,而是将删除的文档ID插入到DELETED表

SELECT * FROM information_schema.`INNODB_FT_DELETED`;

技术分享

如果用户想要彻底删除倒排索引中该文档的分词信息,可以

mysql> SET GLOBAL innodb_optimize_fulltext_only=1;
Query OK, 0 rows affected (0.00 sec)

mysql> OPTIMIZE TABLE fts_a;
+------------+----------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+------------+----------+----------+----------+
| iot2.fts_a | optimize | status | OK |
+------------+----------+----------+----------+
1 row in set (0.08 sec)

mysql> SELECT * FROM information_schema.`INNODB_FT_DELETED`;
+--------+
| DOC_ID |
+--------+
| 7 |
+--------+
1 row in set (0.00 sec)

mysql> SELECT * FROM information_schema.`INNODB_FT_BEING_DELETED`;
+--------+
| DOC_ID |
+--------+
| 7 |
+--------+
1 row in set (0.00 sec)

运行OPTIMIZE TABLE 可以将记录彻底删除,并且彻底删除的文档ID会记录到INNODB_FT_BEGIN_DELETED中。此外,由于7这个文档一倍删除,因此不允许在插入这个文档ID,否则会抛出异常

mysql> INSERT INTO fts_a SELECT 7,‘I like this days‘;
ERROR 182 (HY000): Invalid InnoDB FTS Doc ID

stopword列表(stopword list)是本节最后阐述的一个概念,其表示该列表中的word不需要对其进行索引分词操作。例如,对于the这个单词,由于其不具有具体的意义,因此将其视为stopword,InnoDB存储引擎有一张默认的stopword列表,在information_schema架构下,表名为INNODB_FT_DEFAULT_STOPWORD,默认为36个stopword可以通过参数innodb_ft_server_stopword_table来定义stopword列表,如

mysql> CREATE TABLE innodb_ft_bug (
 -> value VARCHAR(18) NOT NULL DEFAULT ‘‘
 -> ) ENGINE=INNODB DEFAULT CHARSET=utf8; #此处必须为utf8不然会碰到bug
Query OK, 0 rows affected (0.07 sec)

mysql> SET GLOBAL innodb_ft_server_stopword_table=‘iot2/innodb_ft_bug‘;
Query OK, 0 rows affected (0.00 sec)

遇到bug的情形

mysql> CREATE TABLE user_stopword(VALUE VARCHAR(30))ENGINE=INNODB;
Query OK, 0 rows affected (0.03 sec)
mysql> SET GLOBAL innodb_ft_server_stopword_table=‘iot2/user_stopword‘;
ERROR 1231 (42000): Variable ‘innodb_ft_server_stopword_table‘ can‘t be set to the value of ‘iot2/user_stopword‘

观察错误日志提示

InnoDB: invalid column name for stopword table iot2/user_stopword. Its first column must be named as ‘value‘.

 

 

 

使用全文检索还有以下限制

每张表只能有一个全文检索的索引

由多列组合而成的全文检索的索引必须使用相同的字符集与排序规则

不支持没有单词界定符delimiter的语言,如中文 日文汉语等

 

 

 

 

MySQL中InnoDB全文检索

标签:

热心网友 时间:2022-04-08 21:04

从 MySQL 5.7 开始,开发人员改变了 InnoDB 构建二级索引的方式,采用自下而上的方法,而不是早期版本中自上而下的方法了。在这篇文章中,我们将通过一个示例来说明如何构建 InnoDB 索引。最后,我将解释如何通过为 innodb_fill_factor 设置更合适的值。

索引构建过程

在有数据的表上构建索引,InnoDB 中有以下几个阶段:1.读取阶段(从聚簇索引读取并构建二级索引条目)2.合并排序阶段3.插入阶段(将排序记录插入二级索引)在 5.6 版本之前,MySQL 通过一次插入一条记录来构建二级索引。这是一种“自上而下”的方法。搜索插入位置从树的根部(顶部)开始并达到叶页(底部)。该记录插入光标指向的叶页上。在查找插入位置和进行业面拆分和合并方面开销很大。从MySQL 5.7开始,添加索引期间的插入阶段使用“排序索引构建”,也称为“批量索引加载”。在这种方法中,索引是“自下而上”构建的。即叶页(底部)首先构建,然后非叶级别直到根(顶部)。

示例

在这些情况下使用排序的索引构建:

热心网友 时间:2022-04-08 22:22

这种情况,为什么无法使用索引?
东西多了,而且有很多都是跟like关键字相符的,那是肯定慢的,不过只要不是有上万个相符的,速度不会很慢。

变通的方法?既然不能全文索引,那就只能及时删除没有用的记录了,呵呵。

还有的方法就是改为精确查找,呵呵
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
你见过最古老的东西是什么,有多少年历史 WORD中怎么输出稿纸模式word中怎么输出稿纸模式 女性尿检阴性是什么意思 阴性尿检是什么意思 尿检阴性是什么 win10如何查看电脑配置参数 win10怎样查看电脑配置参数 多地对公职人员提接种要求 亚马逊订单可以退回任何Kohl's商店,7月份生效 亚马逊提供免费退货,珠宝退货卖家要承担运费吗 新的亚马逊退货政策惹争议!官方解答来了 魔方六面还原窍门 股票账户的钱什么时候能转出来 如何用Microsoft excel扇形统计图 形容男生(10~15岁)颜值高、可爱帅气的词语有哪些? 关于菊花的一首古诗和解释 求10-15张15或16岁左右的男生照片,要帅气,不要明星 电热水器的内胆的比较,哪个相比较是最好的? 写关于菊花的古诗 那些10几岁长得帅的男生长大后来都变成什么样子了? 电热水器内胆寿命多长时间? 关于菊花的古诗。 带nfc功能的5g手机有哪些? 10岁帅气男孩啥发型好看 八招教你如何挑选高能电热水器? 歌曲带伴唱的伴奏下载网站在哪? 电热水器搪瓷内胆搪瓷厚度最低该是多少 唐诗《菊花》是什么? 哪一种不锈钢型号多少厚度适合做热水器内胆, 关于“菊花”的古诗有哪些? 电热水器的不锈钢内胆厚度是多少毫米? 有什么好看的网游小说 求几本带有游戏系统穿越类的小说完本的! 求一部男主角带着游戏系统穿越的小说,写的比较搞笑的一千章以上的。 有没有穿越或者现代还有网游的小说呢,要完结的,先说一下,匪大的我都看得差不多了,微微一笑很倾城, 好看的网游小说有哪些?? 参芪五味子片对肝有影响吗? 有什么好看的网游小说???求推荐 参芪五味子片和归脾丸都治疗气血两虚,心脾两虚,有什么不同呢?哪个更滋腻? 谁能介绍介绍好看的已完结的网游或穿越类小说? 没病可以吃参芪五味子片 吗? 穿越网游小说完结推荐 参芪五味子片的注意事项是什么 参芪五味子片可以治疗脑血管硬化吗 参芪五味子片和知柏地黄丸是治疗脾虚的药吗 科目三自动挡难吗 吃五天参芪五味子片/灯盏生脉胶囊效果不大 科目三减档步骤 自动挡驾照考试流程 梦见自已穿了一双破鞋走路,一亲戚说你昨穿一双烂鞋,自已很不好意思,赶快走路怕再被说 吃了参芪五味子片会上火吗?