Mysql我相信大家都很熟悉了,因此在这里就不多做介绍。本文主要介绍关于Mysql的一些高级部分知识。
一.Mysql逻辑架构简介
整体结构如下:
mysql的一大特点就是它的存储引擎!非常灵活小巧,可以根据我们自己的需求进行更换,并且由于Mysql开源,所以我们也可以自己定义适合我们项目的存储引擎。
我们可以看到Mysql的软件架构层次感还是非常明显的,接下来我们就每一层每一层来解释下。
1.1 连接层
将mysql同客户端建立连接,获取权限,维持和管理连接。
1.2 服务层
| Management Serveices & Utilities | 系统控制和管理的工具 |
| SQL Interface | Sql接口,接受用户的sql接口,并且返回用户需要查询的接口 |
| Parser | 解析器。sql命令传入到解析器的时候会被解析器解析和验证(词法分析语法分析等) |
| Optimizer | 查询优化器。在sql语句查询之前会先使用查询优化器进行优化。 |
| Caches & Buffers | 缓存,如果存在该条sql缓存的话就不在执行sql,而是从缓存中直接返回 |
1.3存储引擎层
存储引擎真正负责了Mysql中数据的存储和提取。
1.4数据存储层
将数据存储在计算机的文件系统之中,并完成与存储引擎的交换。
一条sql大致的查询流程
- mysql 客户端先通过协议与 mysql 服务器建连接,
- 发送查询语句,先检查查询缓存,如果命中,直接返回结果,
- 缓存中没有数据,进行语句解析,首先 mysql 通过关键字将 SQL 语句进行解析,并生成一颗对应的“解析树”。
- 查询优化器当解析树被认为是合法的了,就由优化器将其转化成执行计划。一条查询可以有很多种执行方式, 最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。
二.索引
索引是在存储引擎层来实现的,所以不同的存储引擎实现的索引不一定相同。
2.1 索引是什么?
Mysql中官方对于索引的定义是:索引是帮助Mysql高效获取数据的数据结构。可以知道,索引的本质就是一种数据结构。可以简单理解为一种排好序的快速查找的数据结构。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构。这些数据结构以某种方式指向数据,这样就可以在这些数据结构上使用高效的查找算法,这种数据结构就是:索引!
2.2 索引优缺点
优点:提高了数据的检索和排序的效率。 缺点:1.占空间。索引本身也很大,需要一定的空间来进行存储。 2. 浪费时间。每次进行表中数据的更新或者新增操作时,数据库不仅要保存这些数据,还要对索引进行维护。
2.3 聚簇索引和非聚簇索引
聚簇索引:是一种数据存储方式,其数据行和相邻的主键键值存储在一起。数据文件和索引文件是同一份文件,数据行的排列顺序和索引列的顺序相同,通过主键键值可以直接定位到对应的数据行。innodb引擎使用的就是聚簇索引。
好处:按照聚簇索引来排列顺序,查询一定范围数据的时候,由于数据都是有序的,数据库不用从多个数据块中提取数据,所以节省了大量的IO操作。
限制:
- 目前只有Innodb支持聚簇索引,而MyIsam不支持聚簇索引。
- 由于数据物理排序方式只能有一种,所以一张表中只能有一个聚簇索引,默认情况下是主键,如果没有主键会默认创建一个隐藏列代替。
- 为了充分利用聚簇索引特性,所以innodb表主键列尽量选用有序id,不建议用无序id。
非聚簇索引:数据和索引分开进行存储,b+树索引结构的叶子结点中存放的是数据的指针地址,找到叶子结点中的数据地址后再通过地址定位到对应的数据。
mysql两个引擎比较
MyISAM:
B+Tree叶节点存放的是数据记录的地址,在检索的时候,先找到索引对应的数据记录的地址,再根据地址读取相应的数据记录,这种查找方式被称为“非聚集索引”。
InnoDB:
它的主键索引是聚集索引,即主键和行记录放在同一个叶节点,找到了主键也就找到了行记录;而它的非主键索引,或者说是辅助索引,是非聚集索引,跟MyISAM引擎的非聚集索引不同的是,MyISAM叶节点保存的是地址,而InnoDB是主键,InnoDB非聚集索引的索引文件和数据文件分开存储,索引文件的叶节点只保存主键,在查找时,要先找到叶节点中的主键,再根据主键去主索引文件查找详细行记录;因此,在设计表的时候,主键字段不宜过长。
2.4 Mysql索引的分类
从索引类型来分:
2.4.1 单值索引
一个索引只包含单个列,一张表可以有多个单值索引
2.4.2 唯一索引
索引列的值必须唯一,但是允许有空值。
2.4.3 主键索引
设置为主键后数据库会自动建立索引,innodb为聚簇索引。
2.4.4 复合索引
即一个索引包含多个列
从数据结构来分:
2.4.5 b+索引
2.4.6 哈希索引
从数据存储方式来分
2.4.7 聚簇索引
2.4.8 非聚簇索引
2.5索引的创建时机
2.5.1 适合创建索引的情况
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该建立索引
- 外键应该建立索引
- 组合索引比单值索引性价比更高
- 排序字段最好建立索引
- 查询中统计和分组的字段。
2.5.2不适合建立索引的情况
- 表的记录太少
- 经常增删改的表或者字段
- where条件里面用不到的字段不建立索引
- 过滤性不好的不创建索引。
三.Explain性能分析
3.1 概念
使用Explain关键字可以模拟优化器执行Sql语句,从而知道Mysql是如何执行SQL语句的,从而分析我们的查询语句。
用法: explain + Sql语句
使用Explain执行后返回的信息:
3.2 具体字段分析
3.2.1 id
select查询的一组序列号,包含一组数据,表示查询中执行select子句或者操作表的顺序。
- id相同,执行顺序从上到下顺序执行
- id不同,值越大,越先被执行。
3.2.2 select_type
代表查询类型,主要是用于区别普通查询,联合查询,子查询等复杂查询。
| select_type属性 | 含义 |
|---|---|
| SIMPLE | 简单的 select 查询,查询中不包含子查询或者 UNION |
| PRIMARY | 查询中若包含任何复杂的子部分,最外层查询则被标记为 Primary |
| DERIVED | 在 FROM 列表中包含的子查询被标记为 DERIVED(衍生) MySQL 会递归执行这些子查询, 把结果放在临时表里。 |
| SUBQUERY | 在SELECT或WHERE列表中包含了子查询 |
| DEPEDENT SUBQUERY | 在SELECT或WHERE列表中包含了子查询,子查询基于外层 |
| UNCACHEABLE SUBQUERY | 无法使用缓存的子查询 |
| UNION | 若第二个SELECT出现在UNION之后,则被标记为UNION; 若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED |
| UNION RESULT | 从UNION表获取结果的SELECT |
3.2.3 table
这个数据是基于哪张表的
3.2.4 type
type是查询的访问类型。是较为重要的一个指标,结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般来说,得保证查询至少达到 range 级别,最好能达到 ref。
system
ref: 非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问。
range: 只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的 where 语句中出现 了 between、<、>、in 等的查询这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而 结束语另一点,不用扫描全部索引。
index: 出现index是sql使用了索引但是没有通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组。
all: 将遍历全表以找到匹配的行 \
3.2.5 possible_keys
显示可能应用在这张表中的索引,一个或者多个。查询涉及到的字段上若存在索引,则该索引将会被列出,但是不一定被实际使用!
3.2.6 key
实际使用的索引,如果没有使用索引的话,则为null
3.2.7 key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。key_len字段能够帮我们清楚的检查是否充分的使用了索引!key_len越长,说明索引使用的越充分!
3.2.8 ref
显示索引的哪一列被使用了,如果可能的话是一个常数。哪些列或常量被用于查找索引列上的值。
3.2.9 rows
rows 列显示 MySQL 认为它执行查询时必须检查的行数。越少越好!
3.2.10 Extra
其他额外信息
Using filesort: 说明 mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL 中无法利用索引 完成的排序操作称为“文件排序”。
Using temporary: 使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
Using index: 代表表示相应的 select 操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错! 如果同时出现 using where,表明索引被用来执行索引键值的查找;如果没有同时出现 using where,表明索引只是 用来读取数据而非利用索引执行查找。
Using where: 表明使用了where过滤
3.3 索引优化
3.3.1 全职匹配我最爱
查询的字段按照顺序在索引中都可以匹配到!
3.3.2 最佳左前缀
使用复合索引的话就需要遵循最佳左前缀法则,即如果索引了多列就需要遵循最佳左前缀法则,查询从索引的最左列开始并且不跳过索引中的列。否则会导致无法充分使用索引,甚至索引失效!
3.3.3 不要在索引列上做任何的计算
不在索引列上做任何操作(计算、函数、(自动 or 手动)类型转换),会导致索引失效而转向全表扫描。
等号左边无计算,等号右边无转换。
3.3.4 索引列上不能有范围查询
尽可能将范围查询的字段的索引顺序放在最后
3.3.5 一首打油诗
全职匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE 百分写最右,覆盖索引不写*;
不等空值还有 OR,索引影响要注意;
VAR 引号不可丢,SQL 优化有诀窍。