【InnoDB 存储引擎-索引学习】

19 篇文章 0 订阅


mysql架构图

索引

索引是是一种数据结构,为了快速的查找数据而使用的,是应用程序设计和开发的一个重要方面。若索引太多,应用程序的性能可能会受到影响。而索引太少,对查询性能又会产生影响。要找到一个合适的平衡点,这对应用程序的性能至关重要。

InnoDB存储引擎支持以下几种常见的索引:

❑B+树索引

B+树索引就是传统意义上的索引,这是目前关系型数据库系统中查找最为常用和最为有效的索引,可以稳定的提供高效的查找。B+树索引并不能找到一个给定键值的具体行。B+树索引能找到的只是被查找数据行所在的页。然后数据库通过把页读入到内存,再在内存中进行二分查找,最后得到要查找的数据。B+树是为磁盘或其他直接存取辅助设备设计的一种平衡查找树。在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接。
概述:
B+树概述
B+树索引分类:

聚集索引

聚集索引(clustered index)就是按照每张表的主键构造一棵B+树,同时叶子节点中存放的即为整张表的行记录数据,并按照顺序排列,也将聚集索引的叶子节点称为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。

由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引。在多数情况下,查询优化器倾向于采用聚集索引。因为聚集索引能够在B+树索引的叶子节点上直接找到数据。此外,由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值的查询。查询优化器能够快速发现某一段范围的数据页需要扫描。

以三条数据插入数据库介绍一下
插入sql
注:Recorder Header 是数据库表结构中

聚簇索引实例说明

辅助索引

对于辅助索引(Secondary Index,也称非聚集索引),叶子节点并不包含行记录的全部数据。叶子节点除了包含键值(c列,-1,-2,-3,-4)以外,每个叶子节点中的索引行中还包含了一个**书签(**主键的值)(bookmark)。该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据(回表查询)。由于InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键
辅助索引结构图
辅助索引描述
**注:**page中的 key:7fffff 就是c的值,pointer:就是书签标记主键的位置,可进行回表查询

B+树索引的管理

索引的创建和删除可以通过两种方法,一种是ALTER TABLE,另一种是CREATE/DROP INDEX。若用户想要查看表中索引的信息,可以使用命令SHOW INDEX。
show index
解释:
❑Table:索引所在的表名。
❑Non_unique:非唯一的索引,可以看到primary key是0,因为必须是唯一的。
❑Key_name:索引的名字,用户可以通过这个名字来执行DROP INDEX。
❑Seq_in_index:索引中该列的位置,如果看联合索引idx_a_c就比较直观了。
❑Column_name:索引列的名称。
❑Collation:列以什么方式存储在索引中。可以是A或NULL。B+树索引总是A,即排序的。如果使用了Heap存储引擎,并且建立了Hash索引,这里就会显示NULL了。因为Hash根据Hash桶存放索引数据,而不是对数据进行排序。
❑Cardinality:非常关键的值,表示索引中唯一值的数目的估计值。Cardinality表的行数应尽可能接近1,如果非常小,那么用户需要考虑是否可以删除此索引。
❑Sub_part:是否是列的部分被索引。如果看idx_b这个索引,这里显示100,表示只对b列的前100字符进行索引。如果索引整个列,则该字段为NULL。
❑Packed:关键字如何被压缩。如果没有被压缩,则为NULL。
❑Null:是否索引的列含有NULL值。可以看到idx_b这里为Yes,因为定义的列b允许NULL值。
❑Index_type:索引的类型。InnoDB存储引擎只支持B+树索引,所以这里显示的都是BTREE。
Comment:注释。

索引管理 - FIC (Fast Index Creation)

快速创建索引介绍
**注:**创建索引,需要在服务升级过程中进行创建,因为会导致加锁或者创建新表,如果有修改操作,服务是不可用的,会导致客户体验不好的情况发生,所以不能在业务高峰时期进行

索引管理 - Online DDL

虽然FIC可以让InnoDB存储引擎避免创建临时表,从而提高索引创建的效率。但正如前面小节所说的,索引创建时会阻塞表上的DML操作。OSC虽然解决了上述的部分问题,但是还是有很大的局限性。**MySQL 5.6版本开始支持Online DDL(在线数据定义)**操作,其允许辅助索引创建的同时,还允许其他诸如INSERT、UPDATE、DELETE这类DML操作,这极大地提高了MySQL数据库在生产环境中的可用性。

此外,不仅是辅助索引,以下这几类DDL操作都可以通过“在线”的方式进行操作:
❑辅助索引的创建与删除
❑改变自增长值
❑添加或删除外键约束
❑列的重命名
通过新的ALTER TABLE语法,用户可以选择索引的创建方式:

ALTER TABLE tbl_name
|ADD{INDEX|KEY}[index_name]
index_type[index_option]…
ALGORITHM[=]{DEFAULT|INPLACE|COPY}
LOCK[=]{DEFAULT|NONE|SHARED|EXCLUSIVE}

ALGORITHM指定了创建或删除索引的算法,COPY表示按照MySQL 5.1版本之前的工作模式,即创建临时表的方式。INPLACE表示索引创建或删除操作不需要创建临时表。DEFAULT表示根据参数old_alter_table来判断是通过INPLACE还是COPY的算法,该参数的默认值为OFF,表示采用INPLACE的方式

LOCK部分为索引创建或删除时对表添加锁的情况,可有的选择为:
(1)NONE 执行索引创建或者删除操作时,对目标表不添加任何的锁,即事务仍然可以进行读写操作,不会收到阻塞。因此这种模式可以获得最大的并发度。
(2)SHARE 这和之前的FIC类似,执行索引创建或删除操作时,对目标表加上一个S锁。对于并发地读事务,依然可以执行,但是遇到写事务,就会发生等待操作。如果存储引擎不支持SHARE模式,会返回一个错误信息。
(3)EXCLUSIVE 在EXCLUSIVE模式下,执行索引创建或删除操作时,对目标表加上一个X锁。读写事务都不能进行,因此会阻塞所有的线程,这和COPY方式运行得到的状态类似,但是不需要像COPY方式那样创建一张临时表。
(4)DEFAULT DEFAULT模式首先会判断当前操作是否可以使用NONE模式,若不能,则判断是否可以使用SHARE模式,最后判断是否可以使用EXCLUSIVE模式。也就是说DEFAULT会通过判断事务的最大并发性来判断执行DDL的模式。
InnoDB存储引擎实现Online DDL的原理是在执行创建或者删除操作的同时,将INSERT、UPDATE、DELETE这类DML操作日志写入到一个缓存中。待完成索引创建后再将重做应用到表上,以此达到数据的一致性。这个缓存的大小由参数innodb_online_alter_log_max_size控制,默认的大小为128MB。
用户更新的表比较大,并且在创建过程中伴有大量的写事务,如遇到innodb_online_alter_log_max_size的空间不能存放日志时,会抛出类似如下的错误:
Error:1799SQLSTATE:HY000(ER_INNODB_ONLINE_LOG_TOO_BIG)
Message:Creating index’idx_aaa’required more than’innodb_online_alter_log_max_size’bytes of modification log.Please try again.
对于这个错误,用户可以调大参数innodb_online_alter_log_max_size,以此获得更大的日志缓存空间。此外,还可以设置ALTER TABLE的模式为SHARE,这样在执行过程中不会有写事务发生,因此不需要进行DML日志的记录。
需要特别注意的是,由于Online DDL在创建索引完成后再通过重做日志达到数据库的最终一致性,这意味着在索引创建过程中,SQL优化器不会选择正在创建中的索引。

Cardinality值

在这里插入图片描述

Cardinality代表该索引列的不重复值的数量;并不是在所有的查询条件中出现的列都需要添加索引。对于什么时候添加B+树索引,一般的经验是,在访问表中很少一部分时使用B+树索引才有意义。对于性别字段、地区字段、类型字段,它们可取值的范围很小,称为低选择性。对于不重复的字段加索引意义才大 如:
SELECT*FROM student WHERE sex=‘M’
按性别进行查询时,可取值的范围一般只有’M’、‘F’。因此上述SQL语句得到的结果可能是该表50%的数据(假设男女比例1∶1),这时添加B+树索引是完全没有必要的。相反,如果某个字段的取值范围很广,几乎没有重复,即属于高选择性,则此时使用B+树索引是最适合的。例如,对于姓名字段,基本上在一个应用中不允许重名的出现。

怎样查看索引是否是高选择性的呢?可以通过SHOW INDEX结果中的列Cardinality来观察。Cardinality值非常关键,表示索引中不重复记录数量的预估值。同时需要注意的是,Cardinality是一个预估值,而不是一个准确值,基本上用户也不可能得到一个准确的值。在实际应用中,Cardinality/n_rows_in_table应尽可能地接近1。如果非常小,那么用户需要考虑是否还有必要创建这个索引。故在访问高选择性属性的字段并从表中取出很少一部分数据时,对这个字段添加B+树索引是非常有必要的。

因为MySQL数据库中有各种不同的存储引擎,而每种存储引擎对于B+树索引的实现又各不相同,所以对Cardinality的统计是放在存储引擎层进行的。数据库对于Cardinality的统计都是通过采样(Sample)的方法来完成的。

在InnoDB存储引擎中,Cardinality统计信息的更新发生在两个操作中:INSERT和UPDATE。根据前面的叙述,不可能在每次发生INSERT和UPDATE时就去更新Cardinality信息,这样会增加数据库系统的负荷,同时对于大表的统计,时间上也不允许数据库这样去操作。
举例

联合索引

联合索引是指对表上的多个列进行索引。前面讨论的情况都是只对表上的一个列进行索引。联合索引的创建方法与单个索引创建的方法一样,不同之处仅在于有多个索引列。例如,以下代码创建了一张t表,并且索引idx_a_b是联合索引,联合的列为(a,b)。从本质上来说,联合索引也是一棵B+树,不同的是联合索引的键值的数量不是1,而是大于等于2。
示例
注:遵循最左匹配原则,select b from t ,不走索引

覆盖索引

InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。使用覆盖索引的一个好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。

对于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;

覆盖索引的另一个好处是对某些统计问题而言的。还是对于上一小节创建的表buy_log,通过 sql 语句进行分析。
通过b+树索引的叶子节点里的值,可以查询到对应的值,不走聚餐索引;

❑全文索引

支持全文检索。全文索引采用了反向索引(Inverted index)设计。
全文检索(Full-Text Search)是将存储于数据库中的所有的整本书或整篇文章中的任意内容信息查找出来的技术。它可以根据需要获得全文中有关章、节、段、句、词等信息,也可以进行各种统计和分析。从InnoDB 1.2.x版本开始,InnoDB存储引擎开始支持全文检索。

全文检索通常使用倒排索引(inverted index)来实现。倒排索引同B+树索引一样,也是一种索引结构。它在辅助表(auxiliary table)中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。这通常利用关联数组实现,其拥有两种表现形式:
❑inverted file index,其表现形式为{单词,单词所在文档的ID}
❑full inverted index,其表现形式为{单词,(单词所在文档的ID,在具体文档中的位置)}
在这里插入图片描述
在这里插入图片描述

InnoDB存储引擎从1.2.x版本开始支持全文检索的技术,其采用full inverted index的方式。在InnoDB存储引擎中,将(DocumentId,Position)视为一个“ilist”。因此在全文检索的表中,有两个列,一个是word字段,另一个是ilist字段,并且在word字段上有设有索引。此外,由于InnoDB存储引擎在ilist字段中存放了Position信息,故可以进行Proximity Search,而MyISAM存储引擎不支持该特性。

正如之前所说的那样,倒排索引需要将word存放到一张表中,这个表称为Auxiliary Table(辅助表)。在InnoDB存储引擎中,为了提高全文检索的并行性能,共有6张Auxiliary Table,目前每张表根据word的Latin编码进行分区。Auxiliary Table是持久的表,存放于磁盘上。然而在InnoDB存储引擎的全文索引中,还有另外一个重要的概念FTS Index Cache(全文检索索引缓存),其用来提高全文检索的性能。

FTS Index Cache是一个红黑树结构,其根据(word,ilist)进行排序。这意味着插入的数据已经更新了对应的表,但是对全文索引的更新可能在分词操作后还在FTS Index Cache中,Auxiliary Table可能还没有更新。InnoDB存储引擎会批量对Auxiliary Table进行更新,而不是每次插入后更新一次Auxiliary Table。当对全文检索进行查询时,Auxiliary Table首先会将在FTS Index Cache中对应的word字段合并到Auxiliary Table中,然后再进行查询。这种merge操作非常类似之前介绍的Insert Buffer的功能,不同的是Insert Buffer是一个持久的对象,并且其是B+树的结构。然而FTS Index Cache的作用又和Insert Buffer是类似的,它提高了InnoDB存储引擎的性能,并且由于其根据红黑树排序后进行批量插入,其产生的Auxiliary Table相对较小。

参数innodb_ft_cache_size用来控制FTS Index Cache的大小,默认值为32M。当该缓存满时,会将其中的(word,ilist)分词信息同步到磁盘的Auxiliary Table中。增大该参数可以提高全文检索的性能,但是在宕机时,未同步到磁盘中的索引信息可能需要更长的时间进行恢复。
MySQL数据库支持全文检索(Full-Text Search)的查询,其语法为:
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
}
MySQL数据库通过MATCH()…AGAINST()语法支持全文检索的查询,MATCH指定了需要被查询的列,AGAINST指定了使用何种方法去进行查询。

❑哈希索引

InnoDB存储引擎支持的哈希索引是自适应的,InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引。

Multi-Range Read优化

MySQL5.6版本开始支持Multi-Range Read(MRR)优化。Multi-Range Read优化的目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问,这对于IO-bound类型的SQL查询语句可带来性能极大的提升。Multi-Range Read优化可适用于range,ref,eq_ref类型的查询。

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

对于InnoDB和MyISAM存储引擎的范围查询和JOIN查询操作,MRR的工作方式如下:
❑将查询得到的辅助索引键值存放于一个缓存中,这时缓存中的数据是根据辅助索引键值排序的。
❑将缓存中的键值根据RowID进行排序。
❑根据RowID的排序顺序来访问实际的数据文件
在这里插入图片描述

Index Condition Pushdown(ICP)优化

ICP

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值