热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySQL体系结构和执行计划

MySQL体系结构和执行计划1.前言2.MySQL体系结构2.1MySQLServer2.2存储引擎3.执行计划3.1.如何查看SQL执行计划3.2.执行计划各列说明3.2.1.i

MySQL体系结构和执行计划

  • 1. 前言
  • 2. MySQL体系结构
    • 2.1 MySQL Server
    • 2.2 存储引擎
  • 3. 执行计划
    • 3.1. 如何查看SQL执行计划
    • 3.2. 执行计划各列说明
      • 3.2.1. id
      • 3.2.2. select_type
      • 3.2.3. table
      • 3.2.4. partitions
      • 3.2.5. type(重要)
      • 3.2.6. possible_keys
      • 3.2.7. key
      • 3.2.8. key_len
      • 3.2.9. ref
      • 3.2.10. rows
      • 3.2.11. filtered
      • 3.2.12. Extra


1. 前言

之前的文章都是介绍MySQL体系结构的某一个部分,之后的文章会对整个MySQL的运行流程或者整个运行流程进行讲解。

哈哈,先介绍下之前的MySQL文章,感兴趣的可以看下,如果看到错误麻烦留言,谢谢。如果感觉写的可以,看到有收获,也可以点赞。您的每次点赞都是我写作的动力。

  • MySQL文件系统简介
  • MySQL表字段类型,表空间,表信息
  • MySQL悲观锁,乐观锁,行锁,表锁,共享锁,排他锁,MDL锁,意向锁,间隙锁,next-key lock,死锁
  • MySQL事务
  • MySQL索引
  • MySQL幻读以及当前读引起的问题验证

此文章简单说下MySQL的执行计划,这个是MySQL优化必备的技能。而说到执行计划又不得不提MySQL的体系结构,在这里就同时说明下。

2. MySQL体系结构

MySQL数据库有三层结构。

  • MySQL server : 包括连接层和SQL层
  • 存储引擎层: 包括多种存储引擎。

2.1 MySQL Server


  • 连接层
    应用程序连接到MySQL的时候,首先经过连接层。包括通信协议,线程处理和用户认证三个部分。

    1、通信协议判断请求客户端的兼容情况。2、线程处理即为每个连接获取一个线程.3、用户验证判断用户名的账号和密码是否正确。

  • SQL 层
    这个就比较重要。每条SQL执行的时候都会经过这几个流程,而且这个也是每个学习MySQL都应该清楚的内容。
    处理流程为:当SQL进行查询的时候,依次进行


序号功能说明
1权限判断用于判断账号是否具有库表的访问权限
2查询缓存通过Query Cache 查询,如果有结果直接返回
3解析器对SQL语句进行解析
4预处理对SQL语句进行预处理
5优化器对SQL语句进行优化
6执行计划优化完成之后生成最合适的执行计划
7调用程序API接口调用MySQL的API接口
8存储引擎通过各种存储引擎访问数据,当然MySQL5.7 默认InnoDB

此外Server 层还存储MySQL的函数,视图,存储过程,触发器等。

2.2 存储引擎

MySQL的存储引擎有多种,例如 MyISAM,InnoDB,Archive,Memory,Federated 等
此外还有MySQL 的分支 Percona的存储引擎 TokuDB ,以及MariaDB 的存储引擎等。

Archive 支持压缩功能的存储引擎。
Memory 只在内存中使用。
Federated 支持远程访问 等,就不一一介绍了。

因为在MySQL8.0 之后只支持InnoDB了,但是在面试的时候还会问道MyISAM和InnoDB区别问题,此处列举几个:

1、InnoDB 支持事务,MyISAM 不支持事务
2、InnoDB 支持表级锁和行级锁,但是MyISAM 只支持表级锁
3、InnoDB的文件结尾有 frm 和 ibd ,但是 MyISAM的文件结尾是 frm ,MYI 和MYD。其中 frm 结尾统一代表表结构文件。InnoDB 中 ibd 文件存储了索引和数据,MyISAM 的 MYI 文件代表索引文件,MYD文件代表数据文件。
4、InnoDB 的并发粒度比MyISAM更高。
5、InnoDB 关注的重点是事务,MyISAM关注性能。
6、InnoDB 统计行数必须扫描表数据,MyISAM总行数会单独存放,但是带Where条件也必须查询表数据。
7. InnoDB 不仅缓存数据还缓存索引,MyISAM只缓存索引。

3. 执行计划

当SQL进行一系列的鉴权,解析,预处理,优化器之后生成执行计划,之后调用的是存储引擎。

当我们编写SQL的时候如何看自己SQL编写的好坏呢,是否能够达到快速查询的目的?
这个时候就要学会查看执行计划。

3.1. 如何查看SQL执行计划

Explain + SQL 语句
例如新建student,school 表,并查看执行计划:

-- create table student
CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,`phone` char(11) DEFAULT NULL,`address` varchar(255) DEFAULT NULL,`school_id` int(11) DEFAULT NULL,`school_name` varchar(255) DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-- create table school
CREATE TABLE `school` (`id` int(11) NOT NULL AUTO_INCREMENT,`school_name` varchar(255) DEFAULT NULL,`school_address` varchar(255) DEFAULT NULL,`school_area` varchar(255) DEFAULT NULL,`school_province` varchar(20) DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入数据
insert into student(name,age,phone,address,school_id,school_name,create_time) VALUES
('lihua',15,'13966667777','北京市海淀区',1,'中关村二小',now());
insert into school(school_name,school_address,school_area,school_province,create_time)VALUES
('中关村二小','北京市海淀区中关村','海淀区','北京市',now());
insert into student(name,age,phone,address,school_id,school_name,create_time) VALUES
('lihua1',15,'13966667777','北京市海淀区',1,'中关村二小',now());
insert into school(school_name,school_address,school_area,school_province,create_time)
VALUES('中关村二小2','北京市海淀区中关村','海淀区','北京市',now());-- 查看所有数据
select * from student;
select * from school;

在这里插入图片描述
在这里插入图片描述

-- 查看执行计划
explain select * from student;

执行计划如图所示:
在这里插入图片描述

3.2. 执行计划各列说明


3.2.1. id

Query Optimizer(查询分析器) 所选定的执行计划中查询的序列号。

3.2.2. select_type

查看的类别,通常有三种场景,正常查询,子查询和联合查询。

  • 正常查询:
    simple 属于子查询外和union外其他的查询方式。

示例: explain select * from school

在这里插入图片描述

  • 子查询:
    primary 子查询的最外层查询。
    subquery 子查询的第一个结果集,被用户外部依赖。
    uncached subquery 无法缓存的子查询
    dependent subquery 子查询中的第一个select ,依赖外部的查询结果
    received 衍生表,通过子查询产生的

示例1:

desc select * from student where school_id = (select id from school where school_name = “中关村二小”)
在这里插入图片描述

这里是外部的查询结果是primary,子查询是subquery。

示例2(这个没有什么特别的意义,只做演示):

explain select * from student t,(select count(id) count,school_name from school where school_name = “中关村二小” GROUP BY school_name) t2 where t.id = t2.count
在这里插入图片描述

received 一般是统计或者分组的时候产生的表,然后用来关联查询。

示例3:

explain select * from school where id = (select school_id from student where id = school.id)
在这里插入图片描述

dependent subquery 依赖外部的条件school.id

示例4:

set @p = 1;
explain select * from school where id = (select school_id from student where id = @p);
在这里插入图片描述

通过设置变量来查询就会存在无法缓存的子查询。

  • union 查询

    union union之后的所有select都使用union
    dependent union 子查询中的union
    union result 组合结果

示例:

explain
select * FROM school where id in
(
select id from school where school_name = “中关村二小”
union select id from school where school_name = “中关村二小2”
)
union
select * FROM school where id = 2
在这里插入图片描述

这里 union 就是联合查询会显示,union result 是最后联合查询的结果。
而 dependent union 就是子查询中的union 。

3.2.3. table

表名,可以是衍生表,例如上述select_type中展示 school,

3.2.4. partitions

查询表分区展示结果的分区。
创建新表展示:

CREATE TABLE `test1` (
`id` INT ( 11 ), PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8
PARTITION BY RANGE ( id ) (PARTITION p0 VALUES less than ( 5 ), PARTITION p1 VALUES less than MAXVALUE
);
insert into test1 values (1),(11);
explain select * from test1;

在这里插入图片描述
这里的id 1 和 11 分别在 不同的分区中。

3.2.5. type(重要)

显示连接使用了何种类型,对表所使用的访问方式。
从最好到最差的连接类型为const、eq_reg、ref、range、index和all。
null > system > const > eq_ref > ref > range > index > all

system: 只有一行记录
const: 只通过唯一索引并只查询了一条数据就找到了
eq_ref: 唯一性索引扫描,主键索引或者唯一索引扫描
ref: 非唯一索引
ref_or_null: 比ref多一个null值的查询
unique_subquery: 子查询返回是主键或者唯一索引
index_merge: 多个索引使用后merge后组合
index_subquery: 子查询返回的是索引,但是不是唯一索引或主键
range: 范围查询 beteween/on ,或者 in,超过一定的数据量会变成全表烧苗
index: 全表扫描,但是查询的列全部是索引
all: 全数据扫描

示例:

  • all 查询所有:

explain select * from school;

在这里插入图片描述

  • index 返回索引列:

explain select id from school;

在这里插入图片描述
这两种都是进行的全表扫描,在查看SQL执行情况的时候都是需要优化的。

  • range 范围查询:

explain select id from school where id < 2

在这里插入图片描述

  • ref 普通索引:

--- 增加索引alter table school add index idx_school_name(school_name);-- 查看执行计划EXPLAIN select * from school where school_name &#61; "中关村二小";

在这里插入图片描述

  • ref_or_null 普通索引加上NULl值:

explain select * from school where school_name &#61; "中关村二小" or school_name is null;

在这里插入图片描述

  • eq_ref 唯一索引&#xff1a;

explain select * FROM school where id in (select id from school where school_name &#61; "中关村二小")

在这里插入图片描述

  • const 只查找一行就找到数据:

explain select * from school where id &#61; 1;

在这里插入图片描述

3.2.6. possible_keys

可能使用的key,用于预测。

3.2.7. key

实际用到的索引 。

3.2.8. key_len

查询的结果集的字符长度。
这个可以查看是否充分使用了索引&#xff0c;当计算的时候需要考虑多个点&#xff0c;

  • 字符类型&#xff1a;例如 int 类型 4个字节。
    可以查看我之前的文章说明&#xff1a;MySQL表字段类型&#xff0c;表空间&#xff0c;表信息
  • NULL &#xff1a; 是否为null,长度加1
  • varchar : 长度加2
  • 字符集&#xff0c;latin1 每个字节长度 1&#xff0c;GBK 每个字节长度2&#xff0c;UTF-8 长度 3&#xff0c;utf8mb4 长度4

3.2.9. ref

显示的是列的名字&#xff0c;显示索引的哪一列被使用了&#xff0c;MySQL将根据这些列来选择行&#xff0c;如果可能的话&#xff0c;是一个常数最好 。

3.2.10. rows

mysql查询用于返沪需要的行数&#xff0c;最好的1&#xff0c;可能出现不准确的情况&#xff0c;是预估值。
当进行查询的时候结果越小越好。

3.2.11. filtered

Filtered表示返回结果的行数占需读取行数的百分比 Filtered列的值越大越好。
Filtered列的值依赖于统计信息,例如子查询了100行信息&#xff0c;但是使用的时候只用到50行&#xff0c;就显示50&#xff0c;显示的展示结果的百分比。

3.2.12. Extra

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

  • using index &#xff1a; 查询的所有列都是索引列&#xff0c;即是使用了覆盖索引。
  • using filesort: MySQL中无法利用索引完成的排序操作称为“文件排序”
    已经建立了索引&#xff0c;但是实际的时候没有用到&#xff0c;并新建了索引&#xff0c;例如索引 abc,查询a &#61; “xx” order by c
  • using temporary: 用到了临时表&#xff0c;并且对临时表进行了排序&#xff0c;一般是group by&#xff0c;order by
  • using where : 使用了where 或者 on
  • using join buffer : 是不是用到了join 缓存 ,有缓存大小 show variable like “%join_buffer_size%”
  • impossible where : where总是返回false 例如 where 1&#61;2

推荐阅读
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
  • Explain如何助力SQL语句的优化及其分析方法
    本文介绍了Explain如何助力SQL语句的优化以及分析方法。Explain是一个数据库SQL语句的模拟器,通过对SQL语句的模拟返回一个性能分析表,从而帮助工程师了解程序运行缓慢的原因。文章还介绍了Explain运行方法以及如何分析Explain表格中各个字段的含义。MySQL 5.5开始支持Explain功能,但仅限于select语句,而MySQL 5.7逐渐支持对update、delete和insert语句的模拟和分析。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
author-avatar
筱白
这个世界如果你不努力学习,你就没有生存的机会
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有