热门标签 | 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

推荐阅读
  • 时序数据是指按时间顺序排列的数据集。通过时间轴上的数据点连接,可以构建多维度报表,揭示数据的趋势、规律及异常情况。 ... [详细]
  • SQLite是一种轻量级的关系型数据库管理系统,尽管体积小巧,却能支持高达2TB的数据库容量,每个数据库以单个文件形式存储。本文将详细介绍SQLite在Android开发中的应用,包括其数据存储机制、事务处理方式及数据类型的动态特性。 ... [详细]
  • 本文详细介绍如何在Spring Boot项目中集成和使用JPA,涵盖JPA的基本概念、Spring Data JPA的功能以及具体的操作步骤,帮助开发者快速掌握这一强大的持久化技术。 ... [详细]
  • 本文详细介绍了在 Windows 7 上安装和配置 PHP 5.4 的 Memcached 分布式缓存系统的方法,旨在减少数据库的频繁访问,提高应用程序的响应速度。 ... [详细]
  • 数据库环境:SQLSERVER2005  有一个test表,其表结构及数据如下图1。其中,id是主键,mid是当前节点,pid是父节点。要求:查出每个节点的根节点,如图2所示。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • APOC 函数详解:路径查询方法
    本文将深入探讨 APOC 库中的路径查询功能,特别是如何利用 `apoc.path.expand` 函数实现灵活的路径查询,包括动态设置最大路径长度等高级特性。 ... [详细]
  • 拖拉切割直线 ... [详细]
  • VS Code 中 .vscode 文件夹配置详解
    本文介绍了 VS Code 中 .vscode 文件夹下的配置文件及其作用,包括常用的预定义变量和三个关键配置文件:launch.json、tasks.json 和 c_cpp_properties.json。 ... [详细]
  • 探讨如何在 Propel 1.5 版本中,通过 Query 功能实现包含多个条件的连接查询,特别是针对 MySQL 数据库的操作。 ... [详细]
  • 本文探讨了SQLAlchemy ORM框架中如何利用外键和关系(relationship)来建立表间联系,简化复杂的查询操作。通过示例代码详细解释了relationship的定义、使用方法及其与外键的相互作用。 ... [详细]
  • 本文探讨了在使用 ElementUI 的 el-select 组件时,@change 事件与 @keyup.enter.native 事件之间存在的冲突问题,并提供了相应的解决策略。 ... [详细]
  • 本文介绍了在解决Hive表中复杂数据结构平铺化问题后,如何通过创建视图来准确计算广告日志的曝光PV,特别是针对用户对应多个标签的情况。同时,详细探讨了UDF的使用方法及其在实际项目中的应用。 ... [详细]
  • 深入解析轻量级数据库 SQL Server Express LocalDB
    本文详细介绍了 SQL Server Express LocalDB,这是一种轻量级的本地 T-SQL 数据库解决方案,特别适合开发环境使用。文章还探讨了 LocalDB 与其他轻量级数据库的对比,并提供了安装和连接 LocalDB 的步骤。 ... [详细]
  • 本文简要介绍了如何使用 Python Elasticsearch DSL 进行基本和高级查询,包括连接 Elasticsearch、执行简单和复杂查询、聚合、排序及分页等。 ... [详细]
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社区 版权所有