Mysql索引结合explain分析示例

目录
  • 简介
  • 1.索引分类
    • 聚簇索引
  • 为什么选择B+树
    • explain

简介

Mysql 在我们项目中使用是非常广的,当我们数据量大的时候,就需要考虑建立索引了,我感觉这也是一种以空间换时间的方式;在我们查询的时候,通过使用索引来提高速度;那么,我们在使用的过程中,怎么判定有没有走索引呢?有一个explain语句来进行分析,根据阿里的Java编程规范,至少类型要提升到range;我那时候就在想为什么要提升到range呢?后来结合Mysql的索引终于知道explain和Mysql底层B+树的对应关系;注:以下内容都是基于InnoDB引擎;

1.索引分类

索引分为聚簇索引非聚簇索引;那么,我们先来探讨一下聚簇索引;

聚簇索引

那么在InnoDB中,如果没有定义主键,那么会怎么办?

首先,他会看你有没有定义唯一键;如果有唯一键,那么就会把这个唯一键当作主键来建立索引;如果连唯一键也没有的话,就会默认创建一个隐藏列 row_id 通过这个row_id来建立索引;所以,由于有这个机制(这个机制是为了配合普通索引的),使用Innodb的话,还是,需要有一个主键 最好是递增主键;不用白不用;(还有,就是主键尽量小一点,如果像UUID一样,问题很多 第一:主键被其他普通索引叶子使用,占用空间 第二:插入的时候,需要随机访问I/O,并且,容易导致页分裂)

聚簇索引的结构 假设,我们主键递增,它的结构示意图如下:

这是一个简单示意图:一页数据能存16k 所以,第一层节点数据肯定比这多多了; 但是,我们可以得到一个结论: 对于非叶子节点存的是主键 + 指针 对于叶子节点存的是 主键 + 真实的数据;

普通索引的结构 假设以 create index idx_t1_bcd on t1(b, c, d)来建立索引; 其示意图如下:

对于普通的索引来说,采用的也是B+树结构,但是: 对于 非叶子节点来说存的是 创建索引的字段(b,c,d) + 指向数据指针 对于叶子节点来说 存的是 创建索引的字段(b,c,d) + 主键的指针;

这里由于存的是主键的指针出现会导致回表:普通索引为什么需要这么设计(为什么不存数据)? 个人理解原因如下:

  • 如果,普通索引也要存下数据的话,那么需要内存空间太大了;
  • 如果,普通索引也存数据的话,当发生修改的话,就需要修改全部的数据;

所以,很明显这个普通索引是比聚簇索引占用空间小很多的,这个特性在count(*) 的时候会用到;

那么,为了解决回表问题,覆盖索引来进行解决

为什么选择B+树

刚刚已经介绍了Mysql 聚簇索引和普通索引的特征;那么,现在问题来了?为什么要选择B+树呢?

原因:和Mysql的特性所致:针对磁盘来说 IO是它的一大瓶颈,索引的出现是为了快速找到对应的数据,所以说:IO越少效率越好,(就是磁盘页加载到内存次数越少越好) 那么,为什么使用B+树就会加载的少呢?

举例说明: 我们假设待存储数据一行大小是1k; 所以,我们一页可以存16行数据;假设我们的主键id为bigint类型,长度为8字节(如果是int 4字节),而指针大小为6字节;一页 为 16k 16 * 1024 /14 = 1170,所以,我们非节点页,可以存放1170个主键 + 指针;综上:如果是2层节点的B+树;可以存的数据是 1170 * 16 = 18720行数据;

那么,如果是三层的B+树呢?这时候第一页非叶子节点,可以存1170个主键+ 指针(指向的是非叶子节点) 第二页非叶子节点,也可以存1170个主键 + 指针(指向叶子节点);第三层 每一页 可以存16行数据;所以,总共可以存 1170 * 1170 * 16行数据;(这已经是千万条数据了)而且,第一层或者第二层非叶子节点一般是是缓存在内存中的,其实千万条数据找一或两次就可以了;其他的以此类推; 如果,采用B树,因为它的非叶子节点中也是存数据的层级会高过B+树;

原因2:使用B+树结构时,因为数据是存在叶子节点中,所以,对于访问查询找到第一个值,就可以通过叶子节点的双向链表进行遍历查询;而如果B树,就需要采用中序遍历;

综上: 1.B+树层级会比较低 2.对范围查询效率比较高;

explain

介绍完Mysql索引结构,我们可以来讲解explain了;

这是explain的字段,我记得我刚刚开始的时候是怎么都记不住;后来和索引建立联系以后就记住了;
id :表示表的加载顺序,id 越大越先查询 用于大表驱动小表;如果相关,就从上到下执行;
type: 查询使用了那种类型 从最好到最差 system > const > eq_ref > ref > range > index > ALL;
const:只匹配一次 出行在主键索引或者唯一索引
ref : 非唯一性索引扫描,返回匹配某个单个值的所在行; 就是通过一个where 条件找到一条或多条数据;
range: 范围查询时使用到;最低标准了;
index: 只遍历索引树 比全表扫描好一点点 因为通常来说索引文件比数据文件小;
all : 全表扫描

row :通过采用函数推算出来的要读的条数,涉及索引的选择,正常情况下误差不会很大; extra: Using filesort 文件排序 需要对找出来的数据进行外部排序,不能使用表内索引完成排序; 慢 需要优化
Using temporary : 使用了临时表来保存中间结果 更慢 需要优化
Using index : 使用了覆盖索引 Using where 使用了Where 这两个不用优化
如果,对Using filesort Using temporary为什么慢感兴趣的同学,可以查看我的另一篇文章 Using filesort Using temporary为什么这么慢

从索引树的角度分析为什么ref>range>index

比如说:where key = 4 这个时候,它首先在第一页进行查找(这里它对链表处理过,引入了数组,为了查找快速,使用的是二分查找) 然后,找到数据指针是0005,所以就去0005数据页中,进行查找,(在页中查找也是使用二分查找)找到了第一条数据key = 4,然后,只要找下一条,看看是不是key != 4 如果,不等于4,那么,就找完了;这是ref级别的过程;
然后,where key >= 4;同理,先找到key = 4,然后,因为大于4,所以,就按照叶子节点中的指针向后找,找到底,这个是type = range 的情况;
至于 type = index 其实就是对整个索引树进行遍历 ,比如说:我创建了普通索引 user(姓名,身份证号) 我想把所有的身份证号找出来,这个时候,就可能使用基于索引树的全表扫描了,因为,索引树相对来说内容小一点,如果,全部扫描的话,内存中没有对应数据页还得都去找出来; 通过,这样推理,可以感受到 ref > range > index;

最左前缀原则理解 我们都知道有最左前缀原则,那么,为什么会有这个原则呢?

还是以他为例:因为B+树先是按照b列的值排序的,在b列的值相同的情况下才使用c列进行排序;也就是说b列的值不同的记录中c的值可能是无序的。而现在你跳过b列直接根据c的值去查找,这是做不到的。 所以说:下面sql语句是没有用的;

select * from t1 where c = 1;

但是,针对下面这条语句:从索引层面这个C是用不上的,从系统性能角度,C又是用的上的,它这叫做索引下推,因为它可以根据b = 1的双向链表相后推的时候,直接把不符合条件的C排除掉了;不用先回表查出数据,在进行排除;

select * from t1 where b > 1 and c > 1;

到此这篇关于Mysql索引结合explain分析示例的文章就介绍到这了,更多相关Mysql explain 索引内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL索引优化Explain详解

    在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看.所以我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用. -- 实际SQL,查找用户名为Jefabc的员工 select * from

  • MySQL如何基于Explain关键字优化索引功能

    explain显示了MySQL如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句.简单讲,它的作用就是分析查询性能. explain关键字的使用方法很简单,就是把它放在select查询语句的前面. mysql查看是否使用索引,简单的看type类型就可以.如果它是all,那说明这条查询语句遍历了所有的行,并没有使用到索引. 比如:explain select * from company_info where cname like '%小%' explain

  • mysql之explain使用详解(分析索引)

    explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了,如: explain select * from statuses_status where id=11; explain列的解释 table:显示这一行的数据是关于哪张表的 type:这是重要的列,显示连接使用了何种类型.从最好到最差的连接类型为const.eq_reg.ref.range.indexhe和all

  • Mysql实验之使用explain分析索引的走向

    概述 索引是mysql的必须要掌握的技能,同时也是提供mysql查询效率的手段.通过以下的一个实验可以理解?mysql的索引规则,同时也可以不断的来优化sql语句 实验目的 本实验是为了验证组合索引的 最左原则 说明 此实验只是为了验证实际使用索引的结果,请忽略设计的合理性 准备工作 1.用户表一张,有uid ,user_name,real_name ,eamil等字段,详细见建表语句 2.在user_name字段下增加一个简单索引user_name,在email,mobile,age三个字段下

  • Mysql索引结合explain分析示例

    目录 简介 1.索引分类 聚簇索引 为什么选择B+树 explain 简介 Mysql 在我们项目中使用是非常广的,当我们数据量大的时候,就需要考虑建立索引了,我感觉这也是一种以空间换时间的方式:在我们查询的时候,通过使用索引来提高速度:那么,我们在使用的过程中,怎么判定有没有走索引呢?有一个explain语句来进行分析,根据阿里的Java编程规范,至少类型要提升到range;我那时候就在想为什么要提升到range呢?后来结合Mysql的索引终于知道explain和Mysql底层B+树的对应关系

  • MySQL索引优化实例分析

    目录 1.数据准备 2.实例一 3.MySQL如何选择合适的索引? 4.常见 SQL 深入优化 4.1.Order by与Group by优化 4.2.分页查询优化 4.3.join关联查询优化 4.3.1.数据准备 4.3.2.MySQL 表关联常见的两种算法 4.4.in和exsits优化 4.5.count(*)查询优化 5.索引设计原则 1.数据准备 #1.建立员工表,并创建name,age,position索引,id为自增主键 CREATE TABLE `employees` (  `

  • MySql索引使用策略分析

    MySql索引 索引优点 1.可以通过建立唯一索引或者主键索引,保证数据的唯一性. 2.提高检索的数据性能 3.在表连接的连接条件 可以加速表与表直接的相连  4.建立索引,在查询中使用索引 可以提高性能 索引缺点 1.在创建索引和维护索引 会耗费时间,随着数据量的增加而增加 2.索引文件会占用物理空间,除了数据表需要占用物理空间之外,每一个索引还会占用一定的物理空间 3.当对表的数据进行 INSERT,UPDATE,DELETE 的时候,索引也要动态的维护,这样就会降低数据的维护速度, (建立

  • mysql索引篇explain命令详解

    目录 前言 key type Extra 前言 mysql中的explain命令可以用来查看sql语句是否使用了索引,用了什么索引,有没有做全表扫描.可以帮助我们优化查询语句.explain出来的信息有10列,文章主要介绍type.key.Extra这几个字段. 演示中涉及到的表结构如下: CREATE TABLE `dept_desc` ( `dept_no` char(4) NOT NULL, `dept_name` varchar(40) NOT NULL, `desc` varchar(

  • MySQL索引使用全程分析

    创建2张用户表user.user2,表结构相同,但user表使用InnoDB存储引擎,而user2表则使用 MyISAM存储引擎. 复制代码 代码如下: -- Table "user" DDL CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `age` tinyint(4) DEF

  • MySQL索引用法实例分析

    本文实例分析了MySQL索引用法.分享给大家供大家参考,具体如下: MYSQL描述: 一个文章库,里面有两个表:category和article.category里面有10条分类数据.article里面有20万条.article里面有一个"article_category"字段是与category里的"category_id"字段相对应的.article表里面已经把 article_category字义为了索引.数据库大小为1.3G. 问题描述: 执行一个很普通的查

  • mysql索引覆盖实例分析

    本文实例讲述了mysql索引覆盖.分享给大家供大家参考,具体如下: 索引覆盖 如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据.这种查询速度非常快,称为"索引覆盖". 假设有一张t15表,在表中建立了一个联合索引:cp(cat_id,price) 当我们使用下面的sql语句,会出现索引覆盖的情况.不信我们可以来查看一下,这里的Extra中显示了Using index,表示这条sql语句刚好用到了索引覆盖. select price from t1

  • mysql索引失效的几种情况分析

    1.最佳左前缀原则--如果索引了多列,要遵守最左前缀原则.指的是查询要从索引的最左前列开始并且不跳过索引中的列. 前提条件:表中已添加复合索引(username,password,age) 分析:该查询缺少username,查询条件复合索引最左侧username缺少,违反了最佳左前缀原则,导致索引失效,变为ALL,全表扫描 分析:查询条件缺少username,password,查询条件复合索引最左侧username,password缺少,违反了最佳左前缀原则,导致索引失效,变为ALL,全表扫描

  • Mysql调优Explain工具详解及实战演练(推荐)

    Mysql调优Explain工具详解以及实战演练 Explain工具介绍Explain分析示例explain 两个变种explain中的列 索引最佳实战索引使用总结: Mysql安装文档参考 Explain工具介绍 使用EXPLAIN关键字可以模拟优化器执行SQL语句,分析你的查询语句或是结构的性能瓶颈 在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是 执行这条SQL 注意:如果 from 中包含子查询,仍会执行该子

随机推荐