mysql的explain中type取值与SQL性能优化的关系
本文转载自[1],对[1]进行了整理
explain结果中的type字段列表:
type字段取值 | 说明 | SQL示范 | 扫描条件 | 建表特点 |
system | 系统表,少量数据,往往不需要进行磁盘IO; | explain select * from mysql.time_zone; |
这些数据已经加载到内存里,不需要进行磁盘IO。 这类扫描是速度最快的。 |
带主键 |
const | 常量连接 |
explain select * from (select * from user where id=1) tmp;(system+const) explain select * from user where id=1;(const) |
(1)命中主键(primary key)或者唯一(unique)索引; (2)被连接的部分是一个常量(const)值; |
带主键 |
eq_ref | 主键索引(primary key)或者非空唯一索引(unique not null)等值扫描 |
explain select * from user,user_ex where user.id=user_ex.id;(All+eq_ref) |
对于前表的每一行(row),后表只有一行被扫描。 再细化一点: (1)join查询; (2)命中主键(primary key)或者非空唯一(unique not null)索引; (3)等值连接; |
含主键 |
ref | 非主键非唯一索引等值扫描 |
explain select * from user,user_ex where user.id=user_ex.id;(All+ref) -------------------------------------------- explain select * from user where id=1; |
把上例eq_ref案例中的主键索引,改为普通非唯一(non unique)索引。 ----------- 当id改为普通非唯一索引后,常量的连接查询,也由const降级为了ref,因为也可能有多于一行的数据被扫描。 ********* ref扫描,可能出现在join里,也可能出现在单表普通索引里,每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型。 |
无主键,含普通索引 |
range | 范围扫描 |
explain select * from user where id between 1 and 4; explain select * from user where id in(1,2,3); explain select * from user where id>3; |
像上例中的between,in,>都是典型的范围(range)查询。 画外音:必须是索引,否则不能批量"跳过"。 |
含主键 |
index | 索引树扫描 |
explain select count(*) from type_learn.user; |
需要扫描索引上的全部数据 id是主键,该count查询需要通过扫描索引上的全部数据来计数。 画外音:此表为InnoDB引擎。 它仅比全表扫描快一点。 |
含主键 |
ALL | 全表扫描(full table scan) | explain select * from user,user_ex where user.id=user_ex.id;(ALL+ALL) | 如果id上不建索引,对于前表的每一行(row),后表都要被全表扫描。 | 无主键 |
上面各类扫描方式由快到慢:
system > const > eq_ref > ref > range > index > ALL
#-------------------------------------------------------------------------------------------------------------------
为type=const创建数据:
mysql> create database type_learn;
mysql> create table user (id int primary key,name varchar(20))engine=innodb;
mysql> insert into user values(1,'shenjian');
mysql> insert into user values(2,'zhangsan');
mysql> insert into user values(3,'lisi');
#-------------------------------------------------------------------------------------------------------------------
为type=eq_ref创建数据:
create table user (id int primary key,name varchar(20))engine=innodb;
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
create table user_ex (id int primary key,age int)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
用于联表查询的情况
#-------------------------------------------------------------------------------------------------------------------
为type=ref创建数据:
create table user (id int,name varchar(20) ,index(id))engine=innodb;
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
create table user_ex (id int,age int,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);
这里的index(id)是增加普通索引,普通索引不是主键索引
主键索引的叶子结点存放了整行记录,普通索引的叶子结点存放了主键ID,查询的时候需要做一次回表查询
一定要回表查询么?
不一定,当查询的字段刚好是索引的字段或者索引的一部分,就可以不用回表,这也是索引覆盖的原理
#-------------------------------------------------------------------------------------------------------------------
为type=range,index创建数据:
create table user (id int primary key,name varchar(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');
#-------------------------------------------------------------------------------------------------------------------
为type=ALL创建数据:
create table user (id int,name varchar(20))engine=innodb;
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
create table user_ex (id int,age int)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);
#-------------------------------------------------------------------------------------------------------------------
建立正确的索引,对数据库性能的提升很重要。
总结
各类扫描类型的要点是:
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了解并优化执行计划,非常重要;
Reference:
[1]同一个SQL语句,为啥性能差异咋就这么大呢?(1分钟系列)
[2]主键索引和普通索引的区别
mysql的explain中type取值与SQL性能优化的关系相关推荐
- 汇编语言-016(SCASB 、STOSB 、LODSD 、数组中的取值、二维数组操作、冒泡排序和二分查找、CMPSW )
1: SCASB : (字节)将AL的值与EDI寻址的一个字比较.进行在一个字符串检索特定的字符 .386 .model flat,stdcall.stack 4096 ExitProcess PRO ...
- oracle sql为null值,在SQL Server Oracle MySQL当数据库中查出某值为NULL怎么办
在SQL Server Oracle MySQL当数据库中查出某值为NULL怎么办? 1.MSSQL: ISNULL() 语法 ISNULL ( check_expression , replacem ...
- 从多个Word文档中批量取值,整理到Excel表中。
针对多个内部是表格,并且格式相同的文档,例如:一些Word表格简历.一些调查表.技术交底等.可以一键提取所有文档中固定位置的数据. 按位置提取word文档内容到excel 通常我们要重复提取每个文档中 ...
- python权重是什么意思_在python带权重的列表中随机取值的方法
1 random.choice python random模块的choice方法随机选择某个元素 foo = ['a', 'b', 'c', 'd', 'e'] from random import ...
- 从多个Word文档中批量取值,整理到Excel表中的技能,整理简历者必备
从多个Word文档中批量取值,整理到Excel表中的技能,整 从多个Word文件中提取指定的值到Excel中,也可以理解为把多个Word文件的值放在一个表格中,便于统计或查阅. 本教材提供了4种不同情 ...
- Python中字典取值常用的方法!
字典是Python中比较常见的数据类型之一,它是一种可变容器模型,可以存储任意数量的任意类型的数据,而且字典中的每个元素由一个键和一个值组成,键和值之间用冒号分隔.本文为大家介绍一下Python中字典 ...
- java enumerator_java 中遍历取值异常(Hashtable Enumerator)解决办法
java 中遍历取值异常(Hashtable Enumerator)解决办法 用迭代器取值时抛出的异常:java.util.NoSuchElementException: Hashtable Enum ...
- java中integer的范围_java中integer取值范围是什么
java中integer取值范围是什么 发布时间:2020-08-27 10:01:14 来源:亿速云 阅读:69 作者:小新 这篇文章给大家分享的是有关java中integer取值范围是什么的内容. ...
- mysql 大量数据 更改索引_一文看懂ICP原理--MySQL用索引去表里取数据的一种优化...
概述 今天主要介绍一下mysql的ICP特性,可能很多人都没听过,这里用一个实验来帮助大家加深一下理解. 一.Index_Condition_Pushdown Index Condition Push ...
最新文章
- SQL Server误区30日谈-Day21-数据损坏可以通过重启SQL Server来修复
- 2019 阿里云峰会·北京站正式启动,互联网出海分论坛报名开启...
- ABAP 的历史,现在,和未来的讨论
- ajax 请求post和get,ajax请求get和post
- Alpha 答辩总结
- 科大讯飞新一代语音识别系统揭秘
- ARM通用寄存器和特殊寄存器
- 使用 ASP.NET 2.0 ObjectDataSource 控件(整理自msdn)
- 拓端tecdat|R语言有状态依赖强度的非线性、多变量跳跃扩散过程模型似然推断分析股票价格波动
- 一图精通python3
- ZZNUOJ_用C语言编写程序实现1236:数的逆转(附完整源码)
- 数仓理论知识之什么是度量,什么是粒度,什么是事实,什么是维度
- 小技巧-不使用js制作高级足球比赛赛程表
- 【教程】手机远程连接另一台手机的termux进行拍照
- Android入门小项目--微信登录界面源码(倒计时、fragement切换、activity信息传递)
- ABAP基本数据类型
- LINUX——账号和权限管理
- PBC下载、安装及基本使用
- echarts 获取点击的y轴数值_四川Y轴前后钢板防护罩哪里卖
- CGED2020总结
热门文章
- linux apache添加多站点配置(Ubuntn和Centos)
- Tomcat/weblogic session失效时间的几种设置方法
- 男人25岁,别让“努力“毁了你的辉煌
- JS原生封装时间函数 日期格式过滤
- Vue watch如何同时监听多个属性?
- 在ElementUI中改变el-table中的el-table-column样式
- mysql 商品属性_MySQL产品属性表设计
- java main test_java调用main自动执行testng方法一
- vue页面引入多个组件的方法
- svn cvs git的区别