《数据库允许空值,往往是悲剧的开始》一文通过explain来分析SQL的执行计划,来分析null对索引命中情况的影响,有不少朋友留言,问explain结果中的type字段,ref,ALL等不一样的值究竟是什么含义。

今天简单说下,常见的type结果及代表的含义,并且通过同一个SQL语句的性能差异,说明建对索引多么重要。

explain结果中的type字段代表什么意思?

MySQL的官网解释非常简洁,只用了3个单词:连接类型(the join type)。它描述了找到所需数据使用的扫描方式。

最为常见的扫描方式有:

system:系统表,少量数据,往往不需要进行磁盘IO;

const:常量连接;

eq_ref:主键索引(primary key)或者非空唯一索引(unique not null)等值扫描;

ref:非主键非唯一索引等值扫描;

range:范围扫描;

index:索引树扫描;

ALL:全表扫描(full table scan);

画外音:这些是最常见的,大家去explain自己工作中的SQL语句,95%都是上面这些类型。

上面各类扫描方式由快到慢:system > const > eq_ref > ref > range > index > ALL

下面一一举例说明。

1. system

explain select * from mysql.time_zone;

上例中,从系统库mysql的系统表time_zone里查询数据,扫码类型为system,这些数据已经加载到内存里,不需要进行磁盘IO。这类扫描是速度最快的。

explain select * from (select * from user where id=1) tmp;

再举一个例子,内层嵌套(const)返回了一个临时表,外层嵌套从临时表查询,其扫描类型也是system,也不需要走磁盘IO,速度超快。

2. const

数据准备:

create table user(

idint primary key,

namevarchar(20)

)engine=innodb;insert into user values(1,'shenjian');insert into user values(2,'zhangsan');insert into user values(3,'lisi');

const扫描的条件为:(1)命中主键(primary key)或者唯一(unique)索引;(2)被连接的部分是一个常量(const)值;

explain select * from user where id=1;

如上例,id是PK,连接部分是常量1。

画外音:别搞什么类型转换的幺蛾子。

这类扫描效率极高,返回数据量少,速度非常快。

3. eq_ref

数据准备:

create table user(

idint primary key,

namevarchar(20)

)engine=innodb;insert into user values(1,'shenjian');insert into user values(2,'zhangsan');insert into user values(3,'lisi');create tableuser_ex (

idint primary key,

ageint)engine=innodb;insert into user_ex values(1,18);insert into user_ex values(2,20);insert into user_ex values(3,30);insert into user_ex values(4,40);insert into user_ex values(5,50);

eq_ref扫描的条件为,对于前表的每一行(row),后表只有一行被扫描。

再细化一点:(1)join查询;(2)命中主键(primary key)或者非空唯一(unique not null)索引;(3)等值连接;

explain select * from user,user_ex where user.id=user_ex.id;

如上例,id是主键,该join查询为eq_ref扫描。

这类扫描的速度也异常之快。

4. ref

数据准备:

create table user(

idint,

namevarchar(20) ,index(id)

)engine=innodb;insert into user values(1,'shenjian');insert into user values(2,'zhangsan');insert into user values(3,'lisi');create tableuser_ex (

idint,

ageint,index(id)

)engine=innodb;insert into user_ex values(1,18);insert into user_ex values(2,20);insert into user_ex values(3,30);insert into user_ex values(4,40);insert into user_ex values(5,50);

如果把上例eq_ref案例中的主键索引,改为普通非唯一(non unique)索引。

explain select * from user,user_ex where user.id=user_ex.id;

就由eq_ref降级为了ref,此时对于前表的每一行(row),后表可能有多于一行的数据被扫描。

explain select * from user where id=1;

当id改为普通非唯一索引后,常量的连接查询,也由const降级为了ref,因为也可能有多于一行的数据被扫描。

ref扫描,可能出现在join里,也可能出现在单表普通索引里,每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型。

5. range

数据准备:

create table user(

idint primary key,

namevarchar(20)

)engine=innodb;insert into user values(1,'shenjian');insert into user values(2,'zhangsan');insert into user values(3,'lisi');insert into user values(4,'wangwu');insert into user values(5,'zhaoliu');

range扫描就比较好理解了,它是索引上的范围查询,它会在索引上扫码特定范围内的值。

explain select * from user where id between 1 and 4;

explainselect * from user where id in (1,2,3);

explainselect * from user where id>3;

像上例中的between,in,>都是典型的范围(range)查询。

画外音:必须是索引,否则不能批量"跳过"。

6. index

index类型,需要扫描索引上的全部数据。

explain count (*) from user;

如上例,id是主键,该count查询需要通过扫描索引上的全部数据来计数。

画外音:此表为InnoDB引擎。

它仅比全表扫描快一点。

7. ALL

数据准备:

create table user(

idint,

namevarchar(20)

)engine=innodb;insert into user values(1,'shenjian');insert into user values(2,'zhangsan');insert into user values(3,'lisi');create tableuser_ex (

idint,

ageint)engine=innodb;insert into user_ex values(1,18);insert into user_ex values(2,20);insert into user_ex values(3,30);insert into user_ex values(4,40);insert into user_ex values(5,50);

explain select * from user,user_ex where user.id=user_ex.id;

如果id上不建索引,对于前表的每一行(row),后表都要被全表扫描。

今天这篇文章中,这个相同的join语句出现了三次:

(1)扫描类型为eq_ref,此时id为主键;

(2)扫描类型为ref,此时id为非唯一普通索引;

(3)扫描类型为ALL,全表扫描,此时id上无索引;

有此可见,建立正确的索引,对数据库性能的提升是多么重要。

全表扫描代价极大,性能很低,是应当极力避免的,通过explain分析SQL语句,非常有必要。

总结

(1)explain结果中的type字段,表示(广义)连接类型,它描述了找到所需数据使用的扫描方式;

(2)常见的扫描类型有: system > const > eq_ref > ref > range > index > ALL  其扫描速度由快到慢;

(3)各类扫描类型的要点是:

system最快:不进行磁盘IO

const:PK或者unique上的等值查询

eq_ref:PK或者unique上的join查询,等值匹配,对于前表的每一行(row),后表只有一行命中

ref:非唯一索引,等值匹配,可能有多行命中

range:索引上的范围扫描,例如:between/in/>

index:索引上的全集扫描,例如:InnoDB的count

ALL最慢:全表扫描(full table scan)

(4)建立正确的索引(index),非常重要;

(5)使用explain了解并优化执行计划,非常重要;

思路比结论重要,希望大家有收获。本文测试于MySQL5.6。

java中explain什么意思_explain关键字使用解释相关推荐

  1. Java中的synchronized与volatile关键字

    原文出处:http://hukai.me/android-training-course-in-chinese/performance/smp/index.html Java中的"synch ...

  2. Java中的break和continue关键字使用总结

    java中的break和continue关键字使用总结 一.作用和区别 break的作用是跳出当前循环块(for.while.do while)或程序块(switch).在循环块中的作用是跳出当前正在 ...

  3. java中用于定义小数的关键字_Java 中用于定义小数的关键字有两个:( ) 和 ( )。_学小易找答案...

    [填空题]列举至少三种中药饮片现代贮藏方法 [单选题]用于薄壁形零件联接时,应采用 . [填空题]若螺纹的直径和螺纹副的摩擦系数一定, 则拧紧螺母时的效率取决于螺纹的 和 . [单选题]以太网采用的介 ...

  4. 简要解析Java中的throw和throws关键字

    解析Java中的throw和throws关键字 1 throws关键字 1.1 作用 向上抛异常,把异常交给调用处处理,实际上自身并没有处理异常. 1.2 原理 一旦方法体出现异常,仍会在异常代码出生 ...

  5. Java中的对象、private关键字、this关键字、构造方法

    面向对象 概述:Java一种面向对象的程序设计语言,面向对象思想是一种程序设计思想,在面向对象思想的指引下,使用Java语言去设计.开发计算机程序. 这里的对象泛指现实中一切事物,每种事物都具备自己的 ...

  6. java中abstract是什么_java关键字abstract

    在java中我们中abstract关键字来表达抽象.举个例子: 我们说车子都可以跑(run).但有几个轮子,怎么跑,对于不同的车有不同的结果.自行车需要人踩着跑,汽车发动机推动跑等等,那么我们可以车表 ...

  7. java中用于定义小数的关键字_Java中用于定义小数的关键字有两个:() 和 (),后者精度高于前者。...

    1.[ 填空题 ]给Java中的菜单项设置快捷键所使用的类中对应的构造方法为______. 2.[ 主观题 ][程序设计题]编写一个方法hex3704(),要求将一个十进制正整数n转换成十六进制数,其 ...

  8. 关于java中char占用2个字符的解释

    文章来源链接 1.区分字符集和字符编码 字符集:统一的字符编号,仅仅提供字符与编号间的映射.如unicode的符号数量在不断增加,已超百万.详细[https://zh.wikipedia.org/zh ...

  9. JAVA中Explain注解用法,mysql之explain详解(分析索引最佳使用)

    mysql之explain详解(分析索引最佳使用) mysql explain用于分析sql 语句的执行及数据库索引的使用.本文将致力于帮助大家充分理解explain所返回的各项参数,从而使大家快速掌 ...

  10. java中的this.id_Java this关键字

    this关键字是什么? Java有一个关键字叫this. 它是对类的当前实例的引用.它只能在实例的上下文中使用.以下代码显示如何使用this关键字. public class Main { int v ...

最新文章

  1. springboot单元测试类
  2. svn 命令行创建和删除 分支和tags
  3. 编辑器的合并用不了_为什么图片和PDF合并后的PDF页面大小不一
  4. linux系统下搭建php环境之-Discuz论坛
  5. 评价一个软件的3个角度
  6. Python编程:Tkinter图形界面设计(1)
  7. win10设置默认输入法_为什么说win10越来越好用了?(技巧篇)
  8. 数据挖掘与数据化运营实战. 3.12 数据产品
  9. Oracle对表名大小写敏感吗,让Oracle 大小写敏感 表名 字段名 对像名
  10. 火神山医院完工,2月3日收治病人!“云监工”请放心!
  11. vs2017修改服务器地址大全,vs2017更改默认pip安装服务器地址
  12. B00007 快速模幂运算的两个C语言程序
  13. 数据管理(DMS):谁动了线上数据?
  14. 唯品会关键词搜索API接口(item_search-按关键字搜索唯品会商品API接口),唯品会API接口
  15. wsdl2java 命令 服务端_使用Axis2中的工具wsdl2Java的生成客户端和服务端代码
  16. linux vi命令怎么使用方法,Linux下 vi 命令用法
  17. iPhone描述文件怎么用,过期如何处理
  18. 我也来开发2048之确定思路
  19. FakeUserAgentError('Maximum amount of retries reached') 彻底解决办法
  20. 如何用计算机恢复出厂设置,告诉你电脑如何恢复出厂设置

热门文章

  1. linux segmentation fault 信号,linux中 Segmentation fault问题
  2. 【NRF51822】DFU过程梳理
  3. 基于STM32平台的数字温度显示器系统设计
  4. 【python多版本共存】
  5. Unity3D游戏开发从零单排(四) - 制作一个iOS游戏
  6. ***【九度oj-1343】城际公路网
  7. 夜神模拟器-软件apk存放目录
  8. 百度地图自定义图标动画
  9. 跟我一起水疗的哥俩儿,其实挺猛的!
  10. 4种最常用的诡辩方法