带你读Mysql技术内幕[5]——什么是索引

前言:本文是自己的阅读《Mysql技术内幕——InnoDB存储引擎》的笔记,主要是为了将阅读和实践结合起来,途中会穿插自己的理解及自己工作中的实践。我理解阅读一本经典的书,无论是技术书籍还是生活数据,带着目的去读,知道书讲得是什么,并且结合自己的理解,输出一定的文字。

经常在工作中,会遇到某个查询比较慢的时候,小伙伴就会思考是否需要新增一个索引来解决呢?
慢 ——> 索引 ——> 解决
似乎索引是一种能够提高速度的东东,那么到底是什么呢?本文带领你一探究竟。

1. 有哪些索引

InnoDB存储引擎支持的索引主要有:

  1. B+树索引
  2. 全文索引
  3. 哈希索引 (有没有很熟悉,咱们在第二篇文章中说了,Innodb会很智能的自动给我们加上自适应hash索引)

可能有人就会问,什么是B+树索引呢?其内部主要结构是什么样的呢?

2. B+树数据结构

B+树的数据结构整体属于:
数据存放到叶子节点中,非叶子节点只存放相应的索引。
同时B+树的高度十分稳定,一般高度都是2 - 4层,这样的话,每次查询最多只需要进行2到4次的磁盘IO。
带你读Mysql技术内幕[5]——什么是索引_第1张图片

1. 聚集索引

什么是聚集索引?
按照每张表的主键构造一颗B+树,同时叶子节点中存放的是整张表的行记录数据,叶节点的数据页通过双向链表进行连接。

而非聚集索引中,存放的仅仅是键值及其指向数据页的偏移量。

聚集索引的好处?
对于主键的排序查找和范围查找速度很快。因为叶子节点存放的数据就是用户所需要查询的数据。

2. 辅助索引

辅助索引又称为非聚集索引。叶子节点并不包含行记录的全部数据,包含的是键值及对应的数据页偏移量,该偏移量用于判断去哪儿可以找到与索引相对应的行数据。

一般查找过程:通过非聚集索引中的偏向量,找到对应的主键索引的主键,在通过主键索引找到一个完整的行记录。这通常又称为回表查询

记住:Innodb存储引擎是一个索引组织表

下图是一个辅助索引的查找过程
带你读Mysql技术内幕[5]——什么是索引_第2张图片

3. 管理索引

1、如何创建和管理索引

创建索引的方式有两种,第一种是建表的时候,第二种是后续修改。

ALTER  TABLE t ADD KEY ind_id (id);

可以通过如下命令查看表中的索引

SHOW INDEX FROM t\G;

带你读Mysql技术内幕[5]——什么是索引_第3张图片
各个含义如下

字段 含义
Table 索引所在表名
Non_unique 非唯一索引
Key_name 索引名字
Seq_in_index 索引中该列的位置
Column_name 索引所在表名
Collation 列以什么方式存储在索引中,A表示排序,
Cardinality 索引中唯一值的数目的估计值,这个值很关键,会根据该值判断是否使用索引
Sub_part 是否是列的部分为索引
Packed 关键字的压缩方式
Null 索引的列是否包含Null值
Index_type 索引的类型

3. Cardinality值

前面说到了Cardinality对于索引分析十分关键,那么什么是cardinality呢?

这个值主要用于判断某个索引是否真的有用,一般建立索引的原则是:某个字段的取值范围很广,基本上没有重复。则适合于建立B+数索引。
Cardinality值就是用来判断字段是否符合这个特征,因为该值的定义是:不重复记录数据的条数。

可以想一下,如何统计该值呢?
总不可能每次有变化,则将整个表整体计算一遍吧,那样如果数据量超级大的情况下,服务器性能都被计算Cardinality吃掉了,势必会导致insert和update很慢。Innodb采用的是随机抽象的方法。

  1. 想统计B+索引中叶子节点的数量。
  2. 随机抽查8个叶子节点,统计每个页不同记录的个数。
  3. 根据上述给一个预估计值。

4. B+树索引的使用

1. 联合索引

什么是联合索引?
对表中的多个列进行索引,组成一个组合索引。

联合索引在B+树的排列顺序是按照建立索引的顺序排列的,也就是最左原则

比如建立一个订单表:

CREATE TABLE `orders` (
  `order_num` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单号',
  `order_date` datetime NOT NULL COMMENT '订单日期',
  `cust_id` int(11) NOT NULL COMMENT '用户Id',
  `shop_id` int(11) DEFAULT NULL COMMENT '店铺Id',
  PRIMARY KEY (`order_num`),
  KEY `ind_orderNum_date` (`order_num`,`order_date`)
) ENGINE=InnoDB AUTO_INCREMENT=20022 DEFAULT CHARSET=utf8;

组合索引ind_orderNum_date在B+树中是先按照order_num,再按照order_date排序。
因此如下查找是没有办法利用索引的

select * from orders where order_date = '2020-06-07 00:00:00'

下面可以看一下组合索引在B+树中的结构
基本上是一种组合排序的形式,从索引左边元素往右边元素依次排序,当然下面的图只是一个例子
带你读Mysql技术内幕[5]——什么是索引_第4张图片

2. 覆盖索引

什么是覆盖索引?
从辅助索引中就可以得到查询的结果,而不需要再根据辅助索引的key及指针查询聚集索引的记录。

覆盖索引的好处?
查找数据快,并且辅助索引不包含整行记录的所有信息,因此物理大小 小于聚集索引,可以减少大量的IO操作。

并且对于统计性问题,比如求解count()之类的

explain select count(*) from orders where order_date>= '2005-09-30 00:00:00';

按照索引的最左原则,按道理是无法利用到ind_orderNum_date索引的,但是分析发现:
在这里插入图片描述
并且看explain结果中Extra是Using Index,这就代表利用了覆盖索引。

3. 优化器选择不使用索引

比如下面的查询

explain select * from orders where order_num>= '20046' and order_num <= '20058';

系统分析可能使用的索引有PRIMARYind_orderNum_date,系统最后选择了使用PRIMARY,这种方式其实就是一种表扫描的方式。因为用户想要的是全列的数据,无法利用上其他索引。
在这里插入图片描述

4. Multi-Range Read优化

Multi-Range Read优化,又简称为MRR
那么什么是MRR优化呢?
主要目的是减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问。执行计划会自己帮助分析如何进行MRR优化。会自己将范围查询拆分为键值对的查询。

主要使用的查询类型:
type为range、red、eq_ref类型的查询

有哪些好处?

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

5. ICP优化

Index Condition PushDown 优化同样是Msyql5.6开始支持的一种根据索引进行查询的优化方式。

为什么需要ICP?
在此之前的做法是:当进行索引查询时,先根据索引来查找记录,然后再根据where条件过滤记录。
ICP优化之后:Mysql会在取出索引的同时,判断是否可以进行WHERE条件的过滤。有时可以减少上层SQL对记录的拉取,提高数据库整体性能。(如果不满足条件了,则不拉取数据了)

使用哪些查询情况?
主要支持range、ref、eq_ref、ref_or_null类型的查询

5. hash索引

Innodb采用自适应hash索引,系统自己创建并使用,用户无法自己创建。

总结

本文主要讲解了索引的一些基础知识,包括各个索引的区别及底层B+树的结构等,需要对于新版本中的索引的优化加一些注意比如MRR优化,ICP优化等。

你可能感兴趣的:(msyql)