MySQL技术内幕-InnoDB存储引擎-第五章、索引与算法

文章目录

索引与算法

索引太多,应用程序的性能可能会受到影响,索引太少,对查询性能可能又会产生影响。
如果知道数据的使用,从一开始就应该添加索引。如何后期添加索引,需要监控大量的SQL语句进而从中找到问题,这个步骤所需的时间肯定是远远大于初始添加索引所要的时间。

一、InnoDB存储引擎索引概述

几种常见的索引:

  • B+树索引
  • 全文索引
  • 哈希索引
    InnoDB支持的哈希索引是自适应的,InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引

B+树索引的构造类似于二叉树,根据键值快速找到数据。
B+树索引并不能找到给定一个键值的具体行,B+树索引能找到的只是被查找数据行所在的页,然后数据库将页读入到内存,再在内存中进行查找,最后得到要查找的数据

二、数据结构与算法

1、二分查找法(找到页之后,具体哪条记录是通过二分查找得到的)

数据必须有序,根据前面的学习,每页Page Directory中的槽是按照主键的顺序存放的,对于某一条具体记录的查询是通过Page Directory进行二分查找得到的。

2、二叉查找树和平衡二叉树

B+树是由二叉查找树,再由平衡二叉树,B树演变而来。

平衡二叉树首先是一棵二叉查找树,虽然平衡二叉树的查找效率很高,但是维护可能需要一次旋转或者多次。

三、B+树

B+树由B树和索引顺序访问方法演化而来。
B+树是为磁盘或其他存储辅助设备设计的一种平衡查找树。在B+树中,所有记录节点都是按照键值的大小顺序存放在同一层的叶子节点上的,由各个叶子节点指针进行连接。

在这里插入图片描述

1、B+树的插入操作(可能需要拆页)

B+树插入必须保证插入后叶子节点中的记录既然是有序的。
插入要考虑以下三种情况:
在这里插入图片描述
B+树总是会保证平衡,但是为了保证平衡,新插入的键值可能需要做大量的拆分页操作。
由于B+树的结构主要用于磁盘,页的拆分意味着磁盘的操作,所以应该在可能的情况下尽量减少页的拆分操作。

2、B+树的删除操作(填充因子最小50%)

B+树通过填充因子来控制树的删除操作,50%树填充因子可设的最小值。

下面是删除的三种情况,与插入不同的是,删除根据填充因子的变化来衡量。
在这里插入图片描述

四、B+树索引

B+树的高度一般都在2-4层,这也就是说查找某一键值的记录时,最多需要2到4次IO,这倒不错。因为当前一般的机械磁盘每秒至少可以做100次IO,2-4次的IO的意思是查询时间只需0.02-0.04秒/

B+树索引分类(其他的索引比如唯一索引等都属于B+树索引):

  • 聚集索引(存放一整行数据)
  • 辅助索引

1、聚集索引(逻辑上连续,物理上不连续,每个表只有一个)

聚集索引就是按照每张表的主键构造一棵B+树,同时叶子节点存放的是整张表的行记录数据,也将聚集索引的叶子节点称为数据页,数据页通过双向链表进行链接。

由于实际的数据页只能按照一棵B+树进行排序,因此只能拥有一个聚集索引,一般查询优化器倾向于使用聚集索引,因为可以在叶子节点直接找到数据,由于定义了数据的逻辑顺序,聚集索引能很快的访问针对范围值的查询。

数据页存放的是完整的每行的记录,而在非数据页的索引页中,存放的仅仅是键值及指向数据页的偏移量,而不是完整的行记录

在这里插入图片描述
聚集索引逻辑上连续,物理上不连续,通过双向链表链接
聚集索引还有一个好处是排序查找和范围查找非常快。

在这里插入图片描述
可以看到虽然查询语句使用了Order by进行排序,但是实际上并没有所谓的filesort操作,这就是因为聚集索引的特点。

范围查找:
通过叶子节点的上一层中间节点就可以得到页的范围,之后直接读取数据页即可。

在这里插入图片描述

2、辅助索引

对于辅助索引即非聚集索引,叶子节点并不包含行记录的全部数据,叶子节点除了包含键值之外,每个叶子节点中的索引行中还包含了一个书签,该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据。由于InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应的行数据的聚集索引键(主键?)

书签是一个行标识符:可以使用“文件号:页号:槽号”的格式来定位实际的行数据。

在这里插入图片描述

当通过辅助索引来查找数据的时候,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针指向主键索引的主键,然后在通过主键索引来找到完整的行记录。

例子

给表t(主键为a列,再增加一列,创建非聚集索引)

在这里插入图片描述
在这里插入图片描述

使用py_innodb_page_info工具分析表空间,如果分析表空间可以得到:
会增加一个页即为非聚集索引所在页,而且会看到辅助索引的叶子节点包含了列c的值和主键的值。

在这里插入图片描述

3、B+树索引的分裂

在这里插入图片描述
如果顺序插入16个数据,你会发现很多页都是没有满的。导致了页空间的浪费。

如果一直是顺序插入,左边的页可能不会再有记录被插入,从而导致空间的浪费。

B+树页的分裂并不是总是从中间记录分裂的。

InnoDB存储引擎的Page Header中有以下几个部分来保存插入的顺序信息:

  • PAGE_LAST_INSERT
  • PAGE_DIRECTION
  • PAGE_N_DIRECTION

通过上面的信息,InnoDB存储引擎可以决定是向左还是向右边分裂,通过决定分裂点是哪一个,如果插入是随机的,那么取页的中间记录作为分裂点的记录。
不取中间节点为分裂节点的情况:

  • 如果往同意方向插入的记录为5,并且定位到的记录(插入位置的前一条记录)之后还有3条记录,那么分裂点的记录为定位到的记录后的第三条记录,否则就是待插入的记录作为分裂点。

在这里插入图片描述
上面的是插入位置之后超过三条记录的情况。否则就是下面的情况

在这里插入图片描述

4、B+树索引的管理

索引管理(Cardinality值要接近于1,不是实时更新,可以使用Analyze Table命令)

索引创建的两种方法:

  • ALTER TABLE
    在这里插入图片描述
  • CREATE/DROP INDEX
    在这里插入图片描述
    用户可以设置整个列的数据进行索引,也可以只索引一个列的开头部分数据。如下面只索引b列的前100个字段,如:
    在这里插入图片描述

如果用户想要查看表中索引的信息,可以使用命令show index from 表名。

在这里插入图片描述

  • Table:索引所在表名
  • Non_unique:非唯一的索引,primary key是0,因为必须是非唯一的。
  • Key_name:索引名称
  • Seq_in_index:索引中该列的位置
  • Column_name:索引列的名称
  • Collation:列以什么方式存储在索引中,可以是A或者NULL,B+树索引总是A即排序的。
  • Cardinality(英[kɑ:dɪ’nælɪtɪ] 基数):非常关键的值,表示索引中唯一值的数目的估计值。Cardinality的值除表的行数应该尽可能接近1
  • Sub_part:是否是列的部分被索引。如果索引整个列显示NULL。
  • packed:关键字如何被压缩,如果没有显示NULL。
  • Null:是否含有NULL值。
  • Index_type:索引的类型
  • Comment:注释

Cardinality非常关键,优化器根据这个值来判断是否使用索引。但是这个值不是实时更新的即不是每次索引的更新都会更新这个值。因为代价太大了。如果需要更新索引Cardinality的信息,可以使用ANALYZE TABLE命令。

==可能会看到Cardinality为NULL,在某些情况下可能会发生索引建立了却没有用到的情况。==或者对两条基本一样的语句指向explain,但是最后出来的结果不一样,一个使用索引,一个使用全表扫描。这是解决方法就是做一次ANALYZE TABLE操作。可以使索引更好的为你工作。

Fast Index Creation(快速索引创建,只限定于辅助索引,避免创建临时表,主键还是要重建一张表)

MySQL5.5版本之前存在一个问题即对于索引的添加或者删除的这类DDL操作,MySQL的操作过程为:

  • 1、创建临时表,表结构为alter table新定义的结构
  • 2、把原表中的数据导入到临时表
  • 3、接着删除原表
  • 4、最后把临时表重名为原来的表名

如果通过上面的方式添加或者删除索引,需要很长的时间。

InnoDB1.0.x开始支持一种名为Fast Index Creation(快速索引创建)的索引创建方式----简称FIC

对于辅助索引的创建,InnoDB会对表加S锁。创建过程中不需要重建表。因此速度提高很多。删除索引操作就更简单了,InnoDB只需要更新内部视图,并将辅助索引的空间标记为可用,同时删除MySQL数据库内部视图上对该表的索引定义即可。

FIC在索引的创建过程中加了S锁,所以只能对表进行读操作,如果有大量的事务需要对目标表进行写操作,那么数据库的服务同样不可以使用,FIC方式只限定于辅助索引,对于主键的创建和删除同样需要重建一张表。。

Online Schema Change(在线架构改变)

==所谓在线,指的是在事务的创建过程中,可以有读写事务对表进行操作,==这提高了原有MySQL数据库在DDL操作时的并发性。

OSC创建过程:
在这里插入图片描述

Online DDL(允许在辅助索引创建的时候,允许DML操作)

FIC虽然可以让InnoDB存储引擎避免创建临时表,提高效率,但是索引创建时会阻塞表上的DML,OSC解决了部分问题,但是还有局限,5.6版本开始支持Online DDL。允许在辅助索引创建的同时,允许DML操作

不仅仅是索引,以下几类DDL操作都可以通过“在线”的方式进行操作:

  • 辅助索引的创建与删除
  • 改变自增长值
  • 添加或删除外键约束
  • 列的重命名
    在这里插入图片描述
  • ALGORITHM指定了创建或者删除索引的算法,COPY表示5.1之前的工作模式,创建临时表,INPLACE表示索引创建或者删除不需要创建临时表。DEFAULT表示根据参数old_alter_table来判断是通过INPLACE还是COPY的算法,该参数默认INPLACE。
  • Lock部分为索引创建或删除对表添加锁的情况。
    1、NONE:索引创建或者删除时,不添加任何的锁。
    2、SHARE:索引创建或者删除时,添加S锁。
    3、EXCLUSIVE:索引创建或者删除时,对目标表添加X锁。读写事务都不能进行
    4、DEFAULT:判断可否使用NONE模式,如果不能,则判断能否使用SHARE模式,最后判断能否使用EXCLUSIVE模式。也就是说DEFAULT会通过判断事务的最大并发性来判断执行DDL的模式。

Online DDL的原理是早执行创建或者删除操作的同时,将DML操作日志写入到一个缓存中,等到完成索引创建后在将重做应用到表上,达到数据的一致性。缓存大小由innodb_online_alter_log_max_size控制。默认128M。

五、Cardinality值

1、什么是Cardinality?

什么时候添加索引?(字段有高选择性)
  • 对于有高选择性的字段添加索引即字段取值范围很广,几乎没重复。(sex的话只有M和F可以选,它是第选择性的,添加索引就没没有必要)
怎么查看是否有高选择性(通过show index结果中的列Cardinality来观察)

Cardinality是一个预估值,不是准确值。在实际应用中,Cardinality/表行应该尽可能接近1。如果非常小,那么用户需要考虑是否还有必要创建这个索引。

2、InnoDB的Cardinality统计

MySQL有不同的存储引擎,而每种存储引擎对于B+树索引的实现又不同,所以对Cardinality的统计是放在存储引擎层进行的。

Cardinality的统计通过采样而来
  • 在生产环境中,索引更新操作很频繁,如果每次操作都进行Cardinality的统计,会给数据库很大负担。
  • 如果一个表很大,50G,那么统计一次Cardinality会需要很长时间。

因此对于Cardinality的统计都是通过采样的方法来完成的。

Cardinality统计信息更新的两个操作(Insert和update)及策略
  • Insert
  • update
    前面说了不可能每次insert和update就去更新Cardinality信息。这样会增加数据库系统的负荷。

InnoDB存储引擎内部更新Cardinality信息的策略

  • 表中1/16的数据已经发生过变化
  • stat_modified_counter>2 000 000 000(每个表维护一个stat_modified_counter,每次DML更新1行就加1,直到满足阈值则自动收集统计信息,并把此值清0)
InnoDB内部如何进行Cardinality信息统计和更新(默认对8个叶子节点采样)

InnoDB引擎默认对8个叶子节点进行采样,采样过程如下:

  • 取得B+树索引中叶子节点的数量,记为A
  • 随机取8个B+树索引中的叶子节点,统计每个页不同记录的个数。即为P1、P2、P3、…、P8.
  • 计算Cardinality预估值:Cardinality=(P1+…+P8)*A/8.

由于每次是随机取8个叶子节点,所以每次得到的Cardinality值是不同的。

有一种情况每次Cardinality结果一样,就是表足够小。表的叶子节点小于或者等于8,可以设置参数innodb_stats_sample_pages用来设置统计Cardinality对每次采样页的数量,默认为8.

当有NULL值的时候,可以设置参数innodb_stats_method来判断如何对待NULL值

  • ,默认nulls_equal即将null看成相等的值。
  • nulls_unequal即将null视为不等的记录
  • nulls_ignored即忽略null值

当执行SQL语句ANALYZE TABLE、SHOW TABLE STATUS、SHOW INDEX以及访问INFROMATION_SCHEMA架构下的表TABLES和STATISTICS时会导致InnoDB存储引擎去重新计算Cardinality的值。

InnoDB1.2版本新加了很多对Cardinality统计进行设置。

在这里插入图片描述

六、B+树索引的作用

1、不同应用中B+树索引的使用

根据第一张介绍,数据库存在两种不同类型的应用:

  • OLTP
    查询操作只从数据库取得一小部分数据。一般在10条记录以下。
    如根据订单号得到订单信息等。
  • OLAP
    需要访问表中的大量数据,根据这些数据产生查询结果。
    目的是为决策者提供支持,如这个月的消费情况、环比增长等。

2、联合索引

对多个列进行索引。
联合索引的创建方法与单个索引创建的方法一样,不同之处仅仅在于有多个索引列。
创建联合索引例子:
在这里插入图片描述
联合索引也是一棵B+树,不同的说,联合索引的键值的数量不是1,而是大于等于2。
在这里插入图片描述

联合索引好处
  • 联合索引遵循最左前缀原则。
  • 如果第一个键值相同,那么第二个键值是排好序的。如果在一些场景中需要排序,就可以避免一次排序操作。

在这里插入图片描述
在这里插入图片描述
上面创建了两个索引。
如果只对userid进行查询,如:

  • select * from buy_log where userid = 2;

在这里插入图片描述
为什么选择了索引userid,因为叶子节点包含单个键值,所以理论上一个页能放的记录应该更多。

  • select * from buy_log where userid=1 order by buy_date desc limit 3;

在这里插入图片描述

因为buy_date已经排好序了,所以无需对buy_date做额外的排序操作。

如果强制使用userid索引,而不使用联合索引,explain时候extra字段会出现Using filesort即需要一次额外的查询。

在这里插入图片描述

例子

对于联合索引(a,b,c)。
select … from table where a=xxx order by b;
select … from table where a=xxx and b=xxx order by c
上面的都可以直接通过联合索引得到结果,下面的不可以需要一次额外的filesort排序操作。
select … from table where a=xxx order by c;

联合索引示例

联合讲解

  • 不按索引最左列开始查询(多列索引) 例如index(‘c1’, ‘c2’, ‘c3’) where ‘c2’ = ‘aaa’ 不使用索引,where c2 = aaa and c3=sss 不能使用索引
  • 查询中某个列有范围查询,则其右边的所有列都无法使用查询(多列查询)
    Where c1= ‘xxx’ and c2 like = ‘aa%’ and c3=’sss’ 改查询只会使用索引中的前两列,因为like是范围查询
  • 如果第一个字段出现 范围符号的查找,那么将不会用到索引
    EXPLAIN SELECT * from testIndex WHERE b>=3 and c=3 and d=3;
    比如有b,c,d的联合索引,第一个字段b出现范围查找,没有使用索引。
    如果条件是b=xx and c>xx;那么一般会走b这个字段不会走c。
    也就是辅助索引如果是范围就不走?覆盖索引可能会走。
    在这里插入图片描述

3、覆盖索引

InnoDB支持覆盖索引,即从辅助索引就可以直接得到查询的记录,而不要查询聚集索引中的记录。使用覆盖索引的好处是辅助索引不包含整行记录的所有信息,故其远小于聚集索引,因此减少大量IO。

InnoDB版本小于1.0或者MySQL版本为5.0或者以下的,InnoDB存储引擎不支持覆盖索引。

对于InnoDB存储引起的辅助索引而言,由于其包含了主键信息,因此其叶子节点存放的数据为(primary key1,primary key2,…,key1,key2,…)即主键和建立联合索引的字段。
例如,下面的语句都可以通过一次辅助联合索引来完成查询:

  • select key2 from table where key1=xxx;
  • select primary key2,key2 from table where key1=xxx;
  • select primary key1,key2 from table where key1=xxx;
  • select primary key1,primary key2,key2 from table where key1=xxx;

如果要执行下面的语句:

  • select count(*) from buy_log;
    InnoDB存储引擎并不会查询聚集索引来进行统计,由于buy_log表上还有辅助索引,而辅助索引远小于聚集索引,选择辅助索引可以减少IO操作。

在这里插入图片描述

从上图可以看到,possible_keys列为NULL,但是实际执行时优化器却选择了userid索引。而列Extra列为Using Index表示了优化器进行了覆盖索引。

(a,b)联合索引,只根据列B进行条件查询,一般不使用联合索引,但是如果SQL查询是统计信息,并且可以利用到联合索引的信息,那么优化器会选择该联合索引。

  • select count(*) from buy_log where buy_date>=‘2011-01-01’ and buy_date<‘2011-02-01’;
    在这里插入图片描述
    虽然possible_keys为NULL,但是key为userid_2,即表示(userid,buy_date)的联合索引。在列Extra同样发现了Using index提示,表示使用了覆盖索引。

4、优化器选择不使用索引的情况(范围查找、JOIN链接)

当执行EXPLAIN命令进行SQL语句的分析的时候,会发现优化器有索引去查找数据,但是没走索引,直接进行全表扫描来得到数据。这种情况多发生于范围查找、JOIN链接操作等情况下。
如:

  • select * from orderdetails where orderid>10000 and orderid<102000;

通过show index from ordertails;可以得到下面的结果:
在这里插入图片描述
可以看出,表有(OrderId,ProductID)的联合主键,还有列OrderID的单个索引。上述的SQL可以通过扫描OrderID上的索引进行数据查找,然而通过explain,可以看到并没有按照OrderID查找数据。
在这里插入图片描述
在possible_keys一列可以看到查询可以使用PRIMARY、OrderID、OrdersOrder_Details三个索引,但是在最后的索引使用中,优化器选择列PRIMARY聚集索引(包含OrderId,ProductID两个列),也就是表扫描,而非OrderID辅助所以扫描。

上面例子没走OrderID索引而走聚集索引理由

因为用户要查找的是整行数据,而OrderID索引不能覆盖到我们要查找的信息。因此在对OrderID索引查询到指定数据后,还需进行一次书签访问来查找整行数据,虽然OrderID数据是顺序的,但是查找的是一个范围,找到的主键可能不是连续的,因此就要变成磁盘上的离散读操作,如果要查找的数据很少,则优化器会选择辅助索引,但是当访问的数据占整个表的很大一部分的时候(一般20%左右),优化器会通过聚集索引查找数据。

可以使用FORCE INDEX来强制使用某个索引:

  • select * from orderdetails FORCE(OrderId) where orderid>10000 and orderid<102000;

在这里插入图片描述

5、索引提示(INDEX HINT,告诉优化器执行哪个索引)

MySQL数据库支持索引提示(INDEX HINT),显式的告诉优化器使用哪个索引。

有两种情况需要使用到INDEX HINT:

  • MySQL数据库的优化器错误的选择了某个索引,导致SQL语句执行的很慢。但是这种情况很少见。
  • 某SQL语句可以选择的索引非常多。这时优化器选择执行计划时间的开销可能会大于SQL语句本身。

MySQL数据库中Index Hint的语法如下:
在这里插入图片描述

  • select * from t use index(a) where a=1 and b=2;

如果通过使用USE INDEX的索引提示指定优化器走哪个索引。但是优化器实际选择的还是会根据自己的判断进行选择,而如果使用FORCE INDEX来索引提示,如:

  • select * from t FORCE INDEX(a) where a=1 and b=2;

如果用户确定指定某个索引来完成查询,那么最可靠的是使用FORCE INDEX。而不是USE INDEX。

6、Multi-Range Read优化

MRR目的是为了减少磁盘的随机访问。并且将随机访问转化为较为顺序的数据访问。MRR优化适用于range、ref、eq_ref类型的查询。

MRR优点:

  • MRR使数据访问变得较为顺序。在查辅助索引的时候,首先根据得到的查询结果按照主键进行排序,并按主键的顺序进行书签查找。
  • 减少缓冲池中页被替换的次数。
  • 批量处理对键值的查询操作。

InnoDB和MyISAM的范围查询和JOIN查询操作中,MRR的工作方式:

  • 将查询得到的辅助索引键值存放于一个缓存中,这是缓存中给的数据是根据辅助索引键值排序的。
  • 将缓存中的键值根据RowID进行排序
  • 根据RowID的排序顺序来访问实际的数据文件。

如果按照RowID顺序读的话,即按照主键顺序进行访问,可以将重复行为降到最低,否则会出现,以前读一个页到缓存,然后被替换掉,过会又把这个页换入缓存池中。

下面一个是使用MRR一个没使用MRR
在这里插入图片描述

两个执行语句的比较

在这里插入图片描述

MRR例子
  • select * from t where key_part1>=1000 and key_part1<2000 and key_part2 = 10000;

如果没开启MRR使用联合索引(key_part1,key_part2),则先根据第一个字段进行选择,再根据第二个字段,开启MRR之后,则对条件进行拆分,即优化器会将查询条件拆分为(1000,1000)、(1001,1000)、(1002,1000)…(1999,1000)。而不是先找到满足key_part1的所有数据,再通过key_part2筛选。

是否启用MRR优化可以通过参数optimizer_switch中的标记(flag)来控制。如果为on,表示开启。参数read_rnd_buffer_size用来控制键值缓冲区大小,如果大于该值,执行器对已经缓存的数据根据RowID进行排序,并通过RowID来取得数据,默认值为256kb。

7、Index Condition Pushdown(ICP)优化

MySQL5.6开始支持,以前进行索引查询的时候,首先根据索引来查找数据,然后在根据where过滤(where可以过滤的条件是要该索引可以覆盖到的范围),在支持ICP之后,MySQL在取出索引的同时,判断是否进行where的优化,也就是将where的部分过滤操作放在存储引擎层

ICP优化支持range、ref、eq_ref、ref_or_null类型的查询。当优化器使用ICP优化的时候,可在执行计划的列Extra看到Using index condition。

七、哈希算法

1、哈希表

数据库中哈希函数通常使用除法散列的方法,解决哈希冲突使用链表的方式。

在哈希函数的除法散列法中,通过取k除以m的余数,将关键字k映射到m个槽的某一个中去,即哈希函数为:

  • h(k) = k mod m

2、InnoDB存储引擎中的哈希算法

对于除法散列,m的值取略大于2倍的缓冲池页数量的质数,如当前参数innodb_buffer_pool_size的大小为10M,则共有640个16kb的页,对于缓存池页内存的哈希表来说,需要分配640*2=1280个槽。但是1280不是质数,需要取比1280略大的质数,即为1399.

InnoDB存储引擎表空间都有一个space_id,用户所要查询的应该是某个表空间的某个连续16kb的页即偏移量offset。InnoDB存储引擎将space_id左移20位,然后加上这个space_id和offset,即关键字K=space_id<<20+space_id+offset,然后通过除法散列到各个槽中去。

3、自适应哈希索引

数据库自身创建并使用的,DBA本身并不能对其进行干预。

哈希索引只能用来搜索等值的查询,对于其他查找类型如范围查找是不能使用哈希索引的:

  • select * from table where index_col = ‘xxx’;

可以通过参数innodb_adaptive_hash_index来禁用或者启动此特性,默认为开启。

八、全文索引

1、概述

如果需要在博客中查询内容包含单词xxx的文章,可能B+索引不能满足要求,因为xxx可能不满足最左前缀。如:

  • select * from blog where content like ‘%xxx%’;

全文检索是将存储与数据库中的整本书或者整篇文章中的任意内容信息查找出来的技术。可以根据需要获得本文中有关章、节、段、句等信息。

InnoDB存储引擎之前并不支持全文检索技术,InnoDB1.2版本开始,InnoDB支持全文检索。

2、倒排索引

倒排索引在辅助表中存储了单词和单词自身在一个或者多个文档中所在位置之间的映射。这通常利用关联数组来实现:

  • inverted file index,其表现形式为{单词,单词所在文档的ID}
  • full inverted index,表现形式为{单词,(单词所在文档ID,单词在文档中具体位置)}
例子

在这里插入图片描述
其中DocumentId表示进行全文索引文档的ID,Text为存储的内容。
在这里插入图片描述
可以看到code位于文档1和4中,单词days存在文档3,6中,之后再对文档进行全文查询就简单了。

inverted file index仅仅存取文档ID,而full inverted index存储的是对(pair),即(DocumentId,Position)

在这里插入图片描述
full inverted index还存储了单词所在的位置信息,如code这个单词出现在(1:6)即文档1的第6个单词为code。

3、InnoDB全文检索(使用倒排索引,采用full inverted index方式)

InnoDB从1.2.x版本开始支持全文检索的技术,采用full inverted index方式,将(DocumentId,Position)视为一个“ilist”,因此在全文检索的表中,有两个列,一个是word字段,一个是ilist字段,并且在word字段上设置了索引。

正如之前说的,倒装索引需要将word放在一张表中,这个表叫Auxiliary Table(辅助表),在InnoDB中为了提高并行性能,共有6张Auxiliary Table,目前每张表根据word的Latin编码进行分区。

InnoDB使用FTS Index Cache(全文检索索引缓存)用来提高全文检索的性能。

FTS Index Cache是红黑树结果,使用(word,ilist)进行排序。可能造成对全文索引的更新只更新了缓存,没更新Auxiliary Table。InnoDB会批量更新到Auxiliary Table,和Insert Buffer类似。

4、全文检索

在这里插入图片描述
其他略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值