这是一篇mysql大全,学习完这篇文章,相信在日常业务和面试完全不在问题,下面我们来一一介绍

MySQL架构与存储引擎

全局变量和会话变量
要想显式指定是否设置全局或会话变量,使用GLOBAL或SESSION选项:
mysql> SET GLOBAL
mysql> SET SESSION
两个选项均没有,则语句设置会话变量。
查看当前进程列表:
mysql>show PROCESSLIST;

存储引擎

查看mysql提供什么存储引擎:

mysql>show engines;

mysql>show variables like ‘%storage_engine%’;

MyISAM:

表级锁,适用场景:非事务型应用(数据仓库、报表、日志数据)、只读类应用。

Innodb

是一种事务性存储引擎,完全支持事务的ACID特征,支持行级锁(并发程度更高),适用于打多数

OLTP(On-Line Transaction Processing联机事务处理过程,其基本特征是前台接收的用户数据可以立

即传送到计算中心进行处理,并在很短的时间内给出处理结果,是对用户操作快速响应的方式之一)应


对比

mysql的一次session代表什么 mysql session global_数据

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一
般。
表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用。(如OLAP系统-联机分析处理)
行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事
务处理(如OLTP-联机事务处理)系统。
InnoDb行锁
读锁(共享锁):当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行
写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
写锁(排它锁):当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给
这几行上任何锁。
语法
上共享锁的写法:lock in share mode
例:select * from 表 where 条件 lock in share mode
上排它锁的写法:for update
例:select * from 表 where 条件 for update;
注意
1:两个事务不能锁同一个索引。
2:insert、delete、update在事务中都会自动默认加上排它锁。
3:行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

事务

1:查看数据库下面是否支持事务(InnoDB支持)。
show engines;
2:查看mysql当前默认的存储引擎。
show variables like ‘%storage_engine%’;
3:查看某张表的存储引擎。
show create table 表名;

事务的特征(ACID)

mysql的一次session代表什么 mysql session global_mysql_02


查看事务的隔离级别:

show variables like ‘tx_isolation’;

默认为可重复读(REPEATABLE-READ)。

事务的隔离级别:读未提交(READ UNCOMMITTED)、读已提交(READ-COMMITTED)、可重复读

(REPEATABLE-READ)、串行化(SERIALIZABLE)。

修改事务的隔离级别:

--读未提交

set GLOBAL TRANSACTION ISOLATION LEVEL read UNCOMMITTED; ##全局

set SESSION TRANSACTION ISOLATION LEVEL read UNCOMMITTED; ##会话

读已提交

set SESSION TRANSACTION ISOLATION LEVEL read committed;

可重复读

set GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

--串行化

set GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;

也可通过修改my.cnf配置文件,设置如下参数:

transaction_isolatinotallow=REPEATABLE-READ

事务的特性

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据就是脏数据。

不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据做了更新并提交,导

致事务A多次读取同一数据是,结果不一致。

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCD等级,但是系统管理员B就在这时

插入了一条具体的分数记录,当系统管理员A改完后发现还有一条记录没有改过来,就好像发生了幻觉

一样。

注:不可重复读和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读

的问题只需锁住满足条件的行,解决幻读需要锁表。

读未提交

此时,我们将两个会话的事务隔离级别同时设置为读未提交,然后在两个会话中各自开启- -个事务,然后在事务1中插入-条数据,并且删除一条数据,如下图中的第1步与第2步所示。

mysql的一次session代表什么 mysql session global_mysql_03


第1.2步执行完毕以后,事务1并未提交,此时执行步骤3 ,在事务2中查看t1表中的数据,是可以看到事务1中所做出的修改的。

所以,我们可以发现,在读未提交这个隔离级别下,即使别的事务所做的修改并未提交.我们也能看到其修改的数据。

当前事务能够看到别的事务中未提交的数据,我们称这种现象为"脏读”,上例中,事务1并未提交,但是其所作出的修改已经能在事务2中查看到,由于事务1中的修改有可能被回滚,或者数据有可能继续被修改,所以事务2中看到数据是飘忽不定的,并不是最终的数据,并不是提交后的数据,是"脏”的,但是事务2中仍然能看到这些数据,所以,这种显现被称之为脏读,当事务的隔离级别处于“读未提交”时,其并发性能是最强的,但是其隔离性与安全性是最差的。

读已提交

同样,在两个会话中同时开启两个事务,在事务1中修改t1表中的第二条数据,如下图中的1.2步所示,此时,务1并未提交,所以如第3步所示,在事务2中并无法看到事务1中的修改,而当事务1提交以后,事务2中即可看到事务1中的修改,换句话说,就是事务2能够读到事务1提交后的更改,这种隔离级别被称为"读提交”。

mysql的一次session代表什么 mysql session global_数据_04


可重复读我们先来总结一下可重读隔离级别的特性 ,仍然以刚才文章开头的示例为例,下图中,再回话1与回话2中同时开启两个事务,在事务1的事务中修改了t1表的数据以后(将第二条数据的t1str的值修改为test ) , 事务2中查看到的数据仍然是事务1修改之前的数据,即使事务1提交了,在事务2没有提交之前,务2中查看到的数据都是相同的,比如t1表中的第2条数据,不管事务1是否提交,在事务2没有提交之前,这条数据对于事务2来说一直都是没有发生改变的,这条数据在事务2中是可以重复的被读到,所以,这种隔离级别被称为"可重读"。

mysql的一次session代表什么 mysql session global_数据库_05


但是,你可能会有个问题,之前说过,事务的隔离性是由锁来实现的,那么,当上图中的事务1中执行更新语句时,事务1中应该对数据增加了写锁,但是在事务2中,仍然可以进行查询操作,即进行读操作,可是写锁是排他锁,在事务1中已经添加了写锁的情况下, 为什么事务2还可以读取呢?这是因为innodb采用了”-致性非锁定读 ”的机制提高了数据库并发性。一致性非锁定读表示在如果当前行被施加了排他锁 ,那么当需要读取行数据时,则不会等待行上的锁的释放,而是会去读取-一个快照数据,如下图所示:

mysql的一次session代表什么 mysql session global_索引_06


串行化

mysql的一次session代表什么 mysql session global_数据_07


如.上图所示,当将两个会话中的事务隔离级别同时设置为串行化以后,分别在两个会话中开启了事务1与事务2 ,如上图中的第1步和第2步所示,然后,进行第3步,在事务1中插入了-条数据,此时,执行第4步,在事务2中查询表t1的数据,可以,第4步好像被”卡"住了,多等-会儿, 发现第4步并未执行成功,而是报了-个错误,如下图。

脏读、幻读、不可重读的区别

我们一起来总结一下它们之前的区别:

脏读:当前事务可以查看到别的事务未提交的数据(侧重点在于别的事务未提交)。

幻读:幻读的表象与不可重读的表象都让人”惜逼" ,很容易搞混,但是如果非要细分的话,幻读的侧重点在于新增和删除。表示在同一事务中,使用相同的查询语句,第二C次查询时,莫名的多出了一些之前不存在数据,或者莫名的不见了一些数据

可重读:不可重读的侧重点在于更新修改数据。表示在同-事务中,查询相同的数据范围时,同一个数据资源莫名的改变了。

mysql的一次session代表什么 mysql session global_数据库_08

业务设计

逻辑设计

范式设计

第一范式

数据库表中的所有字段都只具有单一属性; 单一属性的列是由基本的数据类型所构成; 表是简单的二

维表;

错误的范式:

mysql的一次session代表什么 mysql session global_数据库_09


第二范式

表中只存在一个业务主键,而不能存在非主键列只对部分主键的依赖关系。

错误的范式:----产品与订单的ID没有直接的关联关系

mysql的一次session代表什么 mysql session global_数据_10


正确的范式

mysql的一次session代表什么 mysql session global_数据_11


第三范式

指每一个非主属性既不部分依赖,也不传递依赖于业务主键,也就是在第二范式的基础上增加了非主键

对主键的传递依赖。

客户姓名和订单编号管理关联 客户编号和客户姓名关联 把客户姓名这列删除,只放到客户表中

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_12


反范式

反范化设计为了提高范式化导致性能和读取的效率问题,从而适当的对数据范式设计进行违反。

通过少量的冗余数据,提高读取效率和性能上的问题,这种方式就是空间换时间。

范式设计&反范式

范式优点:

尽可能减少数据的冗余
范式化比反范式化的更新操作更快
范式化的表比反范式化的表更小。

范式缺点:

对于表的查询需要对多个表进行关联
更难进行索引优化

反范式优点:
减少表的关联
可以更好的进行索引的优化
反范式缺点:
存在数据冗余和冗余数据的维护
多数据的修改需更多的成本去处理

物理设计

命名规范

数据库、 表、字段必须遵循可读性原则。
----库、表、字段全部采用小写,不要使用驼峰式命名,使用有意义的英文词汇,词汇中间以下划线分
隔,如system_config。
数据库、 表、字段必须遵循表意性原则,表的名字能够描述表的功能、模块等。 数据库、 表、字段必
须遵循长名原则,尽可能的少用缩写的名字。 数据库、 表、字段应使用英文或者拼音的专有名词。不
要使用拼音。

数据类型选择

优先考虑使用数字类型。 其次日期和时间类型。 最后字符串类型。 对于相同级别的数据类型,优先考
虑使用占用空间较少的数据类型。 对精度有要求的时候,选择精度高的数据类型。
int<float<double<decimal

datetime 与timestamp 都是日期类型,datetime与时区无关,而timestamp与时区有关。timestamp 本质是使用int进行存储。所以效率会比datetime高。但是要考虑时区的问题。

慢查询

mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。该日志能为SQL语句
的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查
询日志功能。

启动慢查询

启动停止技术慢查询日志

查询

show VARIABLES like ‘%slow_query_log%’; ##启动停止技术慢查询日志

show VARIABLES like ‘%slow_query_log_file%’; ##指定慢查询日志得存储路径及文件(默认和数据文

件放一起)

show VARIABLES like ‘%long_query_time%’; ##指定记录慢查询日志SQL执行时间得伐值(单位:秒,

默认10秒)

show VARIABLES like ‘%log_queries_not_using_indexes%’; ##是否记录未使用索引的SQL

show VARIABLES like ‘log_output’; ##日志存放的地方【TABLE】【FILE】【FILE,TABLE】

设置

set GLOBAL slow_query_log = 1; ##0表示禁用日志,1表示启用日志

set GLOBAL long_query_time=0;

set GLOBAL log_output=‘FILE,TABLE’

慢SQL查看

mysql的一次session代表什么 mysql session global_数据_13


mysql的一次session代表什么 mysql session global_mysql_14

慢查询日志分析工具

mysqldumpslow
需要先安装Perl编译器
语法
mysqldumpslow -s r -t 10 slow-mysql.log -s order (c,t,l,r,at,al,ar) c:总次数 t:总时间 l:锁的时间 r:总数
据行 at,al,ar :t,l,r平均数 【例如:at = 总时间/总次数】 -t top 指定取前面几天作为结果输出
如-显示执行时间最长的前两个:
mysqldumpslow.pl -s t -t 2 D:\Program Files (x86)\mysql-5.7.23-winx64\data\SKY-20180701QMWslow.log
其他慢查询分析工具
pt_query_digest

索引

一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环
境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然
是重中之重。
索引(Index)是帮助MySQL高效获取数据的数据结构。
索引是应用程序设计和开发的一个重要方面。若索引太多,应用程序的性能可能会受到影响。而索引太
少,对查询性能又会产生影响,要找到一个平衡点,这对应用程序的性能至关重要。

概述

索引的影响
1、在表中有大量数据的前提下,创建索引速度会很慢。
2、在索引创建完毕后,对表的查询性能会发幅度提升,但是写性能会降低。
本质:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果。
减少磁盘IO,加速查询。(每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部
分,寻道时间指的是磁臂移动到指定磁道所需要的时间,旋转延迟就是我们经常听说的磁盘转速,传输时
间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不
计。)

数据结构

目的:每次查找数据时把磁盘IO次数控制在一个很小的数量级,最好是常数数量级。

mysql的一次session代表什么 mysql session global_数据库_15

叶子节点存储真实的数据。查找首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二
分查找确定。
b+树性质
1:索引字段要尽量的小
IO次数取决于b+数的高度h,这个高度就是每次查询数据的IO次数,当数据量N一定的情况下,m越大,
h越小;而m = 磁盘块的大小 / 数据项的大小,磁盘块的大小也就是一个数据页的大小,是固定的,如
果数据项占的空间越小,数据项的数量越多,树的高度越低。
b+树要求把真实的数据放到叶子节点而不是内层节点,一旦放到内层节点,磁盘块的数据项会大幅度下
降,导致树增高。
2:索引的最左匹配特性
从数据块的左边开始匹配,在匹配右边的。当b+树的数据项是复合的数据结构,比如(name,age,sex)的
时候,b+数是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,b+树
会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数
据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道下一步该查哪个节点,因为建立搜索
树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。

分类

1:聚簇索引
MyISAM存储引擎:有.frm.MYD.MYI结尾的三个文件,frm结尾的是表结构,MYD结尾的是数据文件,
MYI结尾的就是索引文件。
InnoDB引擎:有.frm.idb两个文件,frm结尾的是表结构,idb结尾的是数据和索引文件。InnoDB存储
引擎在存储数据的时候默认就按照索引的那种树形结构来帮你存。
聚簇索引:建立树形结构,但是叶子节点存的是你表中的一条完整记录,一条完整的数据。索引组织表
中数据也是索引的一部分。同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。
如果未定义主键,MySQL取第一个唯一索引(unique)而且只含非空列(NOT NULL)作为主键,
InnoDB使用它作为聚簇索引。 如果没有这样的列,InnoDB就自己产生一个这样的ID值,它有六个字
节,而且是隐藏的,使其作为聚簇索引。
好处
1:对主键的排序查找和范围查找速度非常快,叶子节点的数据就是用户所要查询的数据。
2:范围查询(range query),即如果要查找主键某一范围内的数据,通过叶子节点的上层中间节点就
可以得到页的范围,之后直接读取数据页即可。
2:非聚簇索引
不是聚簇索引,就是非聚簇索引。非聚簇索引的叶子节点不包含行记录的全部数据。
叶子节点存放的是对应的那条数据的主键字段的值,除了包含键值以外,每个叶子节点中的索引行中还
包含一个书签(bookmark),其实这个书签你可以理解为是一个{‘name字段’,name的值,主键id值}
的这么一个数据。该书签用来告诉InnoDB存储引擎去哪里可以找到与索引相对应的行数据。如果我们
select 后面要的是name,我们直接就可以在辅助索引的叶子节点找到对应的name值,这种我们也可以
称为覆盖索引。

聚集索引与辅助索引相同的是:不管是聚集索引还是辅助索引,其内部都是B+树的形式,即高度是平衡的, 叶子结点存放着所有的数据。 聚集索引与辅助索引不同的是:叶子结点存放的是否是一整行的信息。

类型
normal:普通索引,加速查找。 unique:唯一的,不允许重复的索引。 full text: 全文搜索的索引。
FULLTEXT 用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,普通的 INDEX 也可以。
唯一索引: -主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复) -唯一索引UNIQUE:加速查
找+约束(不能重复)
多列索引: -PRIMARY KEY(id,name):联合主键索引 -UNIQUE(id,name):联合唯一索引 -
INDEX(id,name):联合普通索引

单列索引&联合索引

单列:ALTER table 表名 ADD INDEX name (last_name,first_name) ;
多列:ALTER table 表名 ADD INDEX name(last_name);
ALTER table 表名 ADD INDEX name(first_name);
sql如:SELECT * FROM test WHERE last_name=‘Kun’ AND first_name=‘Li’;
多列:sql会先过滤出last_name符合条件的记录,在其基础上在过滤first_name符合条件的记录。
单列:它会选择一个最严格的索引来进行检索,可以理解为检索能力最强的那个索引来检索,另外一个
利用不上了。
能用上多列索引的场景:

SELECT * FROM test WHERE last_name='Widenius';
SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';
SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty');
SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';

利用不上多列索引的场景:

SELECT * FROM test WHERE first_name='Michael'; SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';

总结:
多列建索引比对每个列分别建索引更有优势,因为索引建立得越多就越占磁盘空间,在更新数据的时候
速度会更慢。
另外建立多列索引时,顺序也是需要注意的,应该将严格的索引放在前面,这样筛选的力度会更大,效
率更高。
联合索引的一个原则:索引是有个最左匹配的原则的,所以建联合索引的时候,将区分度高的放在最左
边,依次排下来,范围查询的条件尽可能的往后边放。 联合索引的第二个好处是在第一个键相同的情
况下,已经对第二个键进行了排序处理,例如在很多情况下应用程序都需要查询某个用户的购物情况,
并按照时间进行排序,最后取出最近三次的购买记录,这时使用联合索引可以帮我们避免多一次的排序
操作,因为索引本身在叶子节点已经排序了。

索引方法(BTREE&HASH)

我们可以在创建上述索引的时候,为其指定索引类型,分两类: hash类型的索引:查询单条快,范围
查询慢 btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持
它)
不同的存储引擎支持的索引类型也不一样: InnoDB 支持事务,支持行级别锁定,支持 B-tree、Fulltext 等索引,不支持 Hash 索引; MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索
引,不支持 Hash 索引; Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持
Full-text 索引; NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索
引; Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;
语法

聚集索引的添加方式 创建时添加 
Create table t1( Id int primary key, )Create table t1( Id int, Primary key(id) )
表创建完了之后添加
Alter table 表名 add primary key(id) 
删除主键索引: Alter table 表名 drop primary key; 
唯一索引: Create table t1( Id int unique, )Create table t1( Id int, Unique key uni_name (id) )
表创建好之后添加唯一索引: alter table s1 add unique key u_name(id); 
删除: Alter table s1 drop index u_name; 
普通索引:
创建: Create table t1( Id int, Index index_name(id) )Alter table s1 add index index_name(id); Create index index_name on s1(id); 
删除: Alter table s1 drop index u_name;
 DROP INDEX 索引名 ON 表名字;

创建索引原则

1.选择唯一性索引
2.为经常需要排序、分组和联合操作的字段建立索引
3.为常作为查询条件的字段建立索引
4.限制索引的数目
5.尽量使用数据量少的索引
6.尽量使用前缀来索引
7.删除不再使用或者很少使用的索引

如何正确使用索引

范围问题

条件中出现这些符号或关键字:>、>=、<、<=、!= 、between…and…、like、大于号、小于号。

mysql的一次session代表什么 mysql session global_mysql_16


mysql的一次session代表什么 mysql session global_mysql_17


mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_18


尽量选择区分度高的列作为索引

比例越大扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就

是0。

mysql的一次session代表什么 mysql session global_索引_19


这里name字段的值均为egon,也就是说name这个字段的区分度很低。回忆b+树的结构,查询的速度

与树的高度成反比,要想将树的高低控制的很低,需要保证:在某一层内数据项均是按照从左到右,从

小到大的顺序依次排开。 而对于区分度低的字段,无法找到大小关系,因为值都是相等的,毫无疑

问,还想要用b+树存放这些等值的数据,只能增加树的高度,字段的区分度越低,则树的高度越高。极

端的情况,索引字段的值都一样,那么b+树几乎成了一根棍。=和in可以乱序

比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可

以识别的形式。

索引列不能参与计算

保持列“干净”,比如from_unixtime(create_time) = ’XXXX-XX-XX就不能使用到索引,原因很简单,b+树

中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。

所以语句应该写成create_time = unix_timestamp(’XXXX-XX-XX’)。

mysql的一次session代表什么 mysql session global_mysql_20


and/or

1、and的工作原理 条件: a = 10 and b = ‘xxx’ and c > 3 and d =4 索引: 制作联合索引(d,a,b,c) 索引

的本质原理就是先不断的把查找范围缩小下来,然后再进行处理,对于连续多个and:mysql会按照联

合索引,从左到右的顺序找一个区分度高的索引字段(这样便可以快速锁定很小的范围),加速查询,即

按照d->a->b->c的顺序。

2、or的工作原理 条件: a = 10 or b = ‘xxx’ or c > 3 or d =4 索引: 制作联合索引(d,a,b,c) 工作原理: 只

要一个匹配成功就行,所以对于连续多个or:mysql会按照条件的顺序,从左到右依次判断,即a->b->c->d。

mysql的一次session代表什么 mysql session global_数据库_21


mysql的一次session代表什么 mysql session global_数据_22


mysql的一次session代表什么 mysql session global_索引_23


对于组合索引mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(指的是范围

大了,有索引速度也慢),比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是

用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

mysql的一次session代表什么 mysql session global_mysql_24


覆盖索引

从非聚簇索引中就可以得到查询记录,而不需要查询聚集索引中的记录。

使用覆盖索引的一个好处是:非聚簇索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因

此可以减少大量的IO操作。

执行计划

作用
表的读取顺序;
数据读取操作的操作类型;
哪些索引可以使用;
哪些索引被实际使用;
表之间的引用;
每张表有多少行被优化器查询;
例:

EXPLAIN select o.ooi_id,ot.oou_description,ot.oou_dealadvice,ot.cd_count from t_o_orderinfo o left join (SELECT *,count(b.ooi_id) cd_count FROM ( SELECT * FROM t_o_orderurge where oou_status = 1 ORDER BY oou_date DESC ) b GROUP BY b.ooi_id) ot on ot.ooi_id = o.ooi_id where o.ooi_id = '1261800';

mysql的一次session代表什么 mysql session global_mysql_25


ID

select查询的序列号,包含一组数字,表示SQL执行的顺序的标识,SQL从大到小的执行。

三种情况 1、id相同,执行顺序由上至下 2、id不同,如果是子查询,id的序号会递增,id值越大优先级

越高,越先被执行; 3、id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,

优先级越高,越先执行;

mysql的一次session代表什么 mysql session global_数据_26


select_type

查询中每个select子句的类型。

mysql的一次session代表什么 mysql session global_mysql_27


SIMPLE:简单的 select 查询,查询中不包含子查询或者UNION。

mysql的一次session代表什么 mysql session global_数据库_28


**PRIMARY:**子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为

PRIMARY。

**DERIVED:**在FROM列表中包含的子查询被标记为DERIVED(衍生)MySQL会递归执行这些子查询, 把结果

放在临时表里。

mysql的一次session代表什么 mysql session global_数据库_29


UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查

询中.

**UNION RESULT:**从UNION表获取结果的SELECT.

mysql的一次session代表什么 mysql session global_mysql_30


table

显示这一步所访问数据库中表名称(显示这一行的数据是关于哪张表的),有时不是真实的表名字,可

能是简称。

mysql的一次session代表什么 mysql session global_数据库_31


partitions

分区信息,如果查询是基于分区表的话,会显示查询将访问的分区。

type

访问类型,对表访问方式,表示MySQL在表中找到所需行的方式。

是较为重要的一个指标,结果值从最好到最坏依次是:

system>const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery >

index_subquery > range > index > ALL

需要记忆的:

system>const>eq_ref>ref>range>index>ALL

system:表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不

计。

const

表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以

很快 如将主键置于where列表中,MySQL就能将该查询转换为一个常量。

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_32


eq_ref

EXPLAIN SELECT * from user_info where id=1; EXPLAIN SELECT * from user_info where phnotallow=16123123;

唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。简单来说,就是多表连接中使用

primary key或者 unique key作为关联条件。

EXPLAIN SELECT * FROM user_info a INNER JOIN user_order b on a.id=b.user_id where b.user_id=1 user_info(id):主键索引

mysql的一次session代表什么 mysql session global_索引_33


ref

非唯一性索引扫描,返回匹配某个单独值的所有行。表的连接匹配条件,即哪些列或常量被用于查找索

引列上的值。

EXPLAIN SELECT * FROM user_info a INNER JOIN user_order b on a.phone=b.phone where b.user_id=1 user_info(phone):普通索引

mysql的一次session代表什么 mysql session global_mysql_34


range

只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引。一般就是在你的where语句

中出现了between、<、>等的查询。这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引

的某一点,而结束语另一点,不用扫描全部索引

EXPLAIN SELECT * FROM user_info where phone BETWEEN 30 and 60; EXPLAIN SELECT * FROM user_info where phone>30 and phone<=60; user_info(phone):普通索引

mysql的一次session代表什么 mysql session global_数据_35


index

Full Index Scan,index与ALL区别为index类型只遍历索引树.

EXPLAIN SELECT `name` FROM user_info; user_info(name):普通索引

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_36

ALL
Full Table Scan,将遍历全表以找到匹配的行

EXPLAIN SELECT * FROM user_info;

mysql的一次session代表什么 mysql session global_数据库_37


possible_keys

指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但

不一定被查询使用。

EXPLAIN SELECT * FROM user_info where phone BETWEEN 30 and 60; EXPLAIN SELECT * FROM user_info where name='dfa' and phone=232; user_info(phone):普通索引

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_38


key

显示MySQL实际决定使用的键(索引),必然包含在possible_keys中。

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的

最大可能长度,并非实际使用长度)。不损失精确性的情况下,长度越短越好 。

字符串类型

根据这个值,就可以判断索引使用情况,特别是在组合索引的时候,判断所有的索引字段是否都被查询用到。 char和varchar跟字符编码也有密切的联系。 latin1占用1个字节,gbk占用2个字节,utf8占用3个字节。(不同字符编码占用的存储空间不同)

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_39

字符类型-索引字段为char类型+不可为Null时:

mysql的一次session代表什么 mysql session global_mysql的一次session代表什么_40


key_len=长度3(utf-8)+1(允许为NULL)
索引字段为varchar类型+不可为Null时:

mysql的一次session代表什么 mysql session global_数据库_41


key_len=长度
3(utf-8)+2(变长)+1(允许为NULL)

数值类型

mysql的一次session代表什么 mysql session global_数据_42


mysql的一次session代表什么 mysql session global_数据_43


datetime类型在5.6中字段长度是5个字节。

总结

变长字段需要额外的2个字节(VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果
列声明的长度超过255,则使用两个字节),所以VARCAHR索引长度计算时候要加2),固定长度字段不
需要额外的字节。
而NULL都需要1个字节的额外空间,所以索引字段最好不要为NULL,因为NULL让统计更加复杂并且需
要额外的存储空间。
复合索引有最左前缀的特性,如果复合索引能全部使用上,则是复合索引字段的索引长度之和,这也可
以用来判定复合索引是否部分使用,还是全部使用。

EXPLAIN SELECT * FROM user_info_2 where phone=232 and name='dfa' ; user_info_2(phone,name)联合索引

mysql的一次session代表什么 mysql session global_数据_44


计算:255*3(VARCHAR)+2(变长)+1(为NULL)+4(INT)+1(为NULL)=733

mysql的一次session代表什么 mysql session global_mysql_45


ref

显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。

EXPLAIN SELECT * FROM user_info a INNER JOIN user_order b on a.id=b.user_id where b.user_id=1

mysql的一次session代表什么 mysql session global_mysql_46


rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。

EXPLAIN select o.ooi_id,ot.oou_description,ot.oou_dealadvice,ot.cd_count from t_o_orderinfo o left join (SELECT *,count(b.ooi_id) cd_count FROM ( SELECT * FROM t_o_orderurge where oou_status = 1 ORDER BY oou_date DESC ) b GROUP BY b.ooi_id) ot on ot.ooi_id = o.ooi_id where o.ooi_id = '1261800';

mysql的一次session代表什么 mysql session global_索引_47


filtered

它指返回结果的行占需要读到的行(rows列的值)的百分比。filtered值只对index和all的扫描有效(这可

以理解,其它场合,通常rows值就等于估算的结果集大小。)

mysql的一次session代表什么 mysql session global_索引_48


Extra

包含不适合在其他列中显示但十分重要的额外信息。

mysql的一次session代表什么 mysql session global_索引_49


mysql的一次session代表什么 mysql session global_数据_50