MySQL笔记高级篇

Posted 爪洼ing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL笔记高级篇相关的知识,希望对你有一定的参考价值。

一、mysql架构介绍

1、环境准备

1、安装MySQL,自己采用的Docker镜像安装MySQL

# 1、拉取镜像
docker pull mysql:5.7

# 2、创建实例并启动
docker run -p 3306:3306 --name mysql \\
-v /root/mysql/log:/var/log/mysql \\
-v /root/mysql/data:/var/lib/mysql \\
-v /root/mysql/conf:/etc/mysql \\
-e MYSQL_ROOT_PASSWORD=123456 \\
-d mysql:5.7

2、新的容器当中不存在vim编辑器,需要安装

执行命令:apt-get update
执行命令:apt-get install vim -y


#说明:执行apt-get install vim命令若出现E: Unable to locate package vim,不要忘了执行apt-get update

3、核心配置文件,修改默认字符集

root@8d87e9c530cf:/etc/mysql# pwd  
/etc/mysql
root@8d87e9c530cf:/etc/mysql# ls
conf.d	my.cnf	my.cnf.fallback  mysql.cnf  mysql.conf.d

#进入容器找到 /etc/mysql/mysql.conf.d 目录,然后对其中mysqld.cnf进行配置
root@8d87e9c530cf:/# cd /etc/mysql/mysql.conf.d/
root@8d87e9c530cf:/etc/mysql/mysql.conf.d# ls
mysqld.cnf

#添加如下 :

[mysqld]
character_set_server=utf8

注意:安装MySQL完毕之后,第一件事就是修改字符集编码。

4、MySQL无法输入中文问题

#退出容器,重新容器,使用 C.UTF-8 编码
docker exec -it 【容器ID/名称】 env LANG=C.UTF-8 bash

至此,进入容器后,登录MySQL,即可输入中文。

5、设置完成后进入MySQL查看其字符集编码

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

进行测试

mysql> create database db02 ;
Query OK, 1 row affected (0.00 sec)

mysql> use db02 ;
Database changed

mysql> create table user(id int not null , name varchar(255));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into user values(1,'张三');
Query OK, 1 row affected (0.00 sec)

mysql> select * from user ;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
+----+--------+
1 row in set (0.00 sec)    

环境搭建完成!

2、安装位置

我们的MySQL安装后,我们可以通过可视化界面去操作,但是MySQL在硬盘上的哪个位置呢 ?

2.1、Windows环境目录结构

D:\\MySQL\\mysql-5.7.33

data目录就是存放我们的具体的数据库!

2.2、Linux环境目录结构

#进入容器,查看mysql配置文件位置!
root@8d87e9c530cf:/# whereis mysql
mysql: /usr/bin/mysql /usr/lib/mysql /etc/mysql /usr/share/mysql

#/etc :配置文件,mysql的配置文件会放在这里面
#/var/lib/mysql: mysql数据存放位置

可以看到我们创建的数据库!

Linux环境下MySQL的安装目录

路径解释
/var/lib/mysqlMySQL数据库文件存放位置
/usr/share/mysql错误消息和字符集文件配置
/usr/bin客户端程序和脚本 mysqladmin mysqldump
/etc/init.d/mysql启停脚本相关

3、MySQL配置文件

1、二进制日志log-bin:主从复制。

# my.cnf
# 开启mysql binlog功能
log-bin=mysql-bin

2、错误日志log-error:默认是关闭的,记录严重的警告和错误信息,每次启动和关闭的详细信息等。

# my,cnf
# 数据库错误日志文件
log-error = error.log

3、查询日志log:默认关闭,记录查询的sql语句,如果开启会降低MySQL整体的性能,因为记录日志需要消耗系统资源。

# my,cnf
# 慢查询sql日志设置
slow_query_log = 1
slow_query_log_file = slow.log

4、数据文件

  • frm文件:存放表结构

  • myd文件:存放表数据

  • myi文件:存放表索引

# mysql5.7 使用.frm文件来存储表结构
# 使用 .ibd文件来存储表索引和表数据
-rw-r-----  1 mysql mysql   8988 Jun 25 09:31 pms_category.frm
-rw-r-----  1 mysql mysql 245760 Jul 21 10:01 pms_category.ibd

4、MySQL逻辑架构

逻辑架构示意图

  • Connectors:指的是不同语言中与SQL的交互。

  • Connection Pool:管理缓冲用户连接,线程处理等需要缓存的需求。MySQL数据库的连接层。

  • Management Serveices & Utilities:系统管理和控制工具。备份、安全、复制、集群等等。。

  • SQL Interface:接受用户的SQL命令,并且返回用户需要查询的结果。

  • Parser:SQL语句解析器。

  • Optimizer:查询优化器,SQL语句在查询之前会使用查询优化器对查询进行优化。就是优化客户端请求query,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果。For Exampleselect uid,name from user where gender = 1;这个select查询先根据where语句进行选取,而不是先将表全部查询出来以后再进行gender过滤;然后根据uidname进行属性投影,而不是将属性全部取出以后再进行过滤。最后将这两个查询条件联接起来生成最终查询结果。

  • Caches & Buffers:查询缓存。

  • Pluggable Storage Engines存储引擎接口。MySQL区别于其他数据库的最重要的特点就是其插件式的表存储引擎(注意:存储引擎是基于表的,而不是数据库)。

  • File System:数据落地到磁盘上,就是文件的存储。

和其他数据库相比,MySQL有点与众不同,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需求选择合适的存储引擎。

逻辑架构分层

  • 连接层:最上层是一些客户端和连接服务,包含本地socket通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

  • 服务层:MySQL的核心服务功能层,该层是MySQL的核心,包括查询缓存,解析器,解析树,预处理器,查询优化器。主要进行查询解析、分析、查询缓存、内置函数、存储过程、触发器、视图等,select操作会先检查是否命中查询缓存,命中则直接返回缓存数据,否则解析查询并创建对应的解析树。

  • 引擎层:存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。

  • 存储层:数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

5、MySQL存储引擎

通过上述我们知道MySQL的存储引擎有十余,最常用的还是InnoDB和MyISAM

mysql> show engines;  #通过命令查询当前MySQL所支持的存储引擎

show variables like 'default_storage_engine%'; #查看当前数据库正在使用的存储引擎,以及默认存储引擎

InnoDB和MyISAM对比

对比项MyISAMInnoDB
外键不支持支持
事务不支持支持
行表锁表锁,即使操作一条记录也会锁住整张表,不适合高并发操作行锁,操作时只锁某一行,不对其他行有影响,适合高并发操作
缓存只缓存索引,不缓存真实数据不仅缓存索引还要缓存真实数据,対内存要求较高,而且内存大小対性能有决定性影响
表空间
关注点性能事务
默认安装YY

6、SQL性能下降的原因

  • 查询语句写的差

  • 索引失效:索引建了,但是没有用上

  • 关联 查询太多join(设计缺陷或者不得已的需求)

  • 服务器调优以及各个参数的设置(缓冲、线程数等)

7、SQL执行顺序

select              # 7
from                # 1
join				# 3
on					# 2
where               # 4 
group by            # 5
having              # 6
distinct			# 8
order by            # 9
limit               # 10

SQL执行顺序分析

8、七种JOIN理论

测试所用的SQL文件

实战七种join

/*AB共有*/
select * from tbl_dept a join tbl_emp b on a.id = b.deptid ;
/*A全部和AB共有*/
select * from tbl_dept a left join tbl_emp b on a.id = b.deptid ;
/*B全部和AB共有*/
select * from tbl_dept a right join tbl_emp b on a.id = b.deptid ;
/*A独占*/
select * from tbl_dept a left join tbl_emp b on a.id = b.deptid where b.id is null;
/*B独占*/
select * from tbl_dept a right join tbl_emp b on a.id = b.deptid where a.id is null;
/*A独占+B独占+AB共有*/
mysql> select * from tbl_dept a right join tbl_emp b on a.id = b.deptid 
    -> union    
    -> select * from tbl_dept a left join tbl_emp b on a.id = b.deptid ;
/*A独占+B独占*/ 
mysql> select * from tbl_dept a left join tbl_emp b on a.id = b.deptid where b.deptid is null
    -> union
    -> select * from tbl_dept a right join tbl_emp b on a.id = b.deptid where a.id is null ;

注意:其中union会进行去重!

二、索引优化分析

1、索引

1、什么是索引

MySQL官方对索引的定义为:索引(INDEX)是帮助MySQL高效获取数据的数据结果。

从而可以获得索引的本质:索引是排好序的快速查找数据结构

索引的目的在于提高查询效率,可以类比字典的目录。如果要查mysql这个这个单词,我们肯定要先定位到m字母,然后从上往下找y字母,再找剩下的sql。如果没有索引,那么可能需要a---z,这样全字典扫描,如果我想找Java开头的单词呢?如果我想找Oracle开头的单词呢???

重点:索引会影响到MySQL==查找(WHERE的查询条件)排序(ORDER BY)==两大功能!

除了数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上

# Linux下查看磁盘空间命令 df -h 
[root@Ringo ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   16G   23G  41% /
devtmpfs        911M     0  911M   0% /dev
tmpfs           920M     0  920M   0% /dev/shm
tmpfs           920M  480K  920M   1% /run
tmpfs           920M     0  920M   0% /sys/fs/cgroup
overlay          40G   16G   23G  41%

我们平时所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种数据结构的索引之外,还有哈希索引(Hash Index)等。

2、索引的优势和劣势

优势

  • 查找:类似大学图书馆的书目索引,提高数据检索的效率,降低数据库的IO成本
  • 排序:通过索引対数据进行排序,降低数据排序的成本,降低了CPU的消耗

劣势

  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的

  • 虽然索引大大提高了查询速度,但是同时会降低表的更新速度,例如对表频繁的进行INSERTUPDATEDELETE。因为更新表的时候,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加的索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

  • 索引只是提高效率的一个因素,如果MySQL有大数据量的表,就需要花时间研究建立最优秀的索引。

3、MySQL索引分类和创建

索引分类

-InnoDB

  • 主键索引:设为主键的字段会自动创建索引(无序手动创建),innodb为聚簇索引
  • 单值索引:一个索引只包含单个列,一个表可以有多个单列索引。
  • 唯一索引:索引列的值必须唯一,但是允许空值。(但是只能有一个null)
  • 复合索引:一个索引包含多个字段。

-MyISAM

  • Full text 全文索引(mysql5.7之前版本,只能用于myISAM存储引擎)

建议:一张表建的索引最好不要超过5个!

索引基本语法

1、建表之后创建索引

/* 1、创建索引 [UNIQUE]可以省略*/
/* 如果只写一个字段就是单值索引,写多个字段就是复合索引 */
CREATE [UNIQUE] INDEX indexName ON tabName(columnName(length));
ALTER TABLE tableName ADD [UNIQUE] INDEX	 indexName ON (columnName(length));

/* 2、删除索引 */
DROP INDEX [indexName] ON tabName;

/* 3、查看索引 */
/* 加上\\G就可以以列的形式查看了 不加\\G就是以表的形式查看 */
SHOW INDEX FROM tabName \\G;

2、使用ALTER命令来为数据表添加索引

/* 1、该语句添加一个主键,这意味着索引值必须是唯一的,并且不能为NULL */
ALTER TABLE tabName ADD PRIMARY KEY(column_list);

/* 2、该语句创建索引的键值必须是唯一的(除了NULL之外,NULL可能会出现多次) */
ALTER TABLE tabName ADD UNIQUE indexName(column_list);

/* 3、该语句创建普通索引,索引值可以出现多次 */
ALTER TABLE tabName ADD INDEX indexName(column_list);

/* 4、该语句指定了索引为FULLTEXT,用于全文检索 */
ALTER TABLE tabName ADD FULLTEXT indexName(column_list);

3、建表的时候添加索引

CREATE TABLE tb01(id INT PRIMARY KEY , NAME VARCHAR(20),UNIQUE(NAME));  #添加唯一索引,主键索引

CREATE TABLE tb01(id INT PRIMARY KEY , NAME VARCHAR(20),KEY(NAME));  	#添加单值索引,主键索引

CREATE TABLE tb02(id INT PRIMARY KEY , NAME VARCHAR(20),age INT ,KEY(NAME,age));  #添加复合索引

4、MySQL索引底层原理 *

数据准备

1.思考
---建表
create table t_emp(id int primary key,name varchar(20),age int);  

--插入数据
insert into t_emp values(5,'d',22);
insert into t_emp values(6,'d',22);
insert into t_emp values(7,'e',21);
insert into t_emp values(1,'a',23);
insert into t_emp values(2,'b',26);
insert into t_emp values(3,'c',27);
insert into t_emp values(4,'a',32);
insert into t_emp values(8,'f',53);
insert into t_emp values(9,'v',13);

--查询
select * from t_emp;

思考: 为什么没有按找顺序插入,输出会排好序呢?

  • 原因是:mysql底层为主键自动创建索引,一定创建索引会进行排序 ,也就是mysql底层真正存储是这样的

为什么要排序呢 ?

  • 因为排序之后在查询就相对比较快了 如查询 id=3的我只需要按照顺序找到3就行啦(如果没有排序大海捞针,全靠运气😸!)

如果是按照链表排序那么查询的时间复杂度是O(n)的,需要做优化!

  • 就是基于页的形式进行管理索引
  • 如 :查询id=4的 直接先比较页 先去页目录中找,再去 数据目录中找

于是就采用如下这种B+Tree的数据结构 :

B-Tree(B树)与B+Tree的区别是什么呢?

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。

​ 从上一节中的B-Tree结构图中可以看到每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果

data数据较大时将会导致每个节点(即一个页)能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查

询时的磁盘I/O次数,进而影响查询效率。在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子

节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

B+Tree相对于B-Tree有几点不同:

  • 非叶子节点只存储键值信息。
  • 所有叶子节点之间都有一个链指针。
  • 数据记录都存放在叶子节点中。

InnoDB存储引擎中页的大小为16KB,一般表的主键类型为INT(占用4个字节)或BIGINT(占用8个字节),指针类型也一般为4或8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值(因为是估值,为方便计算,这里的K取值为〖10〗3)。**也就是说一个深度为3的B+Tree索引可以维护103 * 10^3 * 10^3 = 10亿 条记录**。

实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在24层。MySQL的InnoDB存储引擎在设计时是将==根节点常驻内存==的,也就是说查找某一键值的行记录时最多只需要13次磁盘I/O操作。

  • 1次IO的情况:我们的B+Tree只有2层,由于顶层常驻内存,所以只有查找数据的时候进行一次磁盘IO ;
  • 2次IO情况:B+Tree有三层,同样是顶层查询走内存,所以查到数据需要进行2次磁盘IO ;
  • 3次IO情况:B+Tree有四层,或者B+Tree有三层采用Innodb存储引擎,索引是辅助索引!

聚簇索引和非聚簇索引的区别:

  • 聚簇索引将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据
  • 非聚簇索引将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置

注意:在innodb中,在聚簇索引之上创建的索引称之为辅助索引,非聚簇索引都是辅助索引,像复合索引、单值索引、唯一索引。**辅助索引叶子节点存储的不再是行的物理位置,而是主键值,辅助索引访问数据总是需要二次查找**我们把==回到主键索引树搜索的过程,我们称为回表==

InnoDB

  • InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。

  • 若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。(重点在于通过其他键需要建立辅助索引)

  • 聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索引代替。如果没有这样的索引,InnoDB 会**隐式定义一个主键(类似oracle中的RowId)**来作为聚簇索引。如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

MYISAM

  • MyISAM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树

相关面试题

1、使用聚簇索引的优势

问题: 每次使用辅助索引检索都要经过两次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?

  • 1.由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来查询数据,获得数据更快。

  • 2.辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化;或者是我们需要查找的数据,在上一次IO读写的缓存中没有,需要发生一次新的IO操作时,可以避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储空间大小

2、聚簇索引需要注意什么?

  • 当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出现新增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。
  • 建议使用int类型的自增,方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,主键值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量。

3、 为什么主键通常建议使用自增id

  • 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

4、什么情况下无法利用索引呢?

  • 查询语句中使用LIKE关键字
    在查询语句中使用 LIKE 关键字进行查询时,如果匹配字符串的第一个字符为“%”,索引不会被使用。如果“%”不是在第一个位置,索引就会被使用。

  • 查询语句中使用多列索引
    多列索引是在表的多个字段上创建一个索引,只有查询条件中使用了这些字段中的第一个字段,索引才会被使用。

  • 查询语句中使用OR关键字
    查询语句只有OR关键字时,如果OR前后的两个条件的列都是索引,那么查询中将使用索引。如果OR前后有一个条件的列不是索引,那么查询中将不使用索引。

参考文章

innodb聚簇索引和myisam非聚簇索引

InnoDB 的辅助索引叶子节点为什么不直接保存的记录地址而要存主键键值

B-Tree、B+Tree详解

5、哪些情况需要建索引

  • 主键自动建立主键索引(唯一 + 非空)

  • 频繁作为查询条件的字段应该创建索引

  • 查询中与其他表关联的字段,外键关系建立索引

  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

建的复合索引尽量与Order by 一致

  • 查询中统计或者分组字段(group by也和索引有关)

6、那些情况不要建索引

  • 记录太少的表。

  • 经常增删改的表。

  • 频繁更新的字段不适合创建索引。

  • Where条件里用不到的字段不创建索引。

  • 假如一个表有10万行记录,有一个字段A只有true和false两种值,并且每个值的分布概率大约为50%,那么对A字段建索引一般不会提高数据库的查询速度。索引的选择性是指索引列中不同值的数目与表中记录数的比。如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99。一个索引的选择性越接近于1,这个索引的效率就越高。

性能分析

2、索引性能分析

1、MySQL Query Optimizer

MySQL中专门负责优化SELECT语句的优化器模块

主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供它认为最优的执行计划(它认为最优的数据检索方式,但不见得是DBA认为最优的,这部分最耗费时间)

当客户端像MySQL请求一条Query,命令解析器模块完成请求分类,去别处是SELECT并转发给MySQL Query Optimizer ,MySQL Query Optimizer首先会对整条Query进行优化,处理掉一些常量表达式的预算,直接换算成常量值。并对Query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件,结构调整等。然后分析Query中的Hint信息(如果有),看显示Hint信息是否可以完全确定该Query的执行计划。如果没有Hint或Hint信息还不足以完全确定执行计划,则会读区所涉及对象的统计信息,根据Query进行写相应的计算分析,然后再得出最后的执行计划。

2、MySQL常见瓶颈

CPU:CPU再饱和的时候一般发生再数据装入内存或从磁盘上读区数据的时候

IO:磁盘IO瓶颈发生再装入数据远大于内存容量的时候

服务器硬件的性能瓶颈:top free iostat和vmstat来查看系统的性能状态

3、explain

EXPLAIN:SQL的执行计划,使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的。

EXPLAIN怎么使用

  • 语法:explain + SQL语句

测试

默认以表的形式展示

mysql> explain select * from tbl_emp\\G ;   #/G是表示以列的形式展示
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tbl_emp
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

EXPLAIN能干嘛

可以查看以下信息

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

4、explain字段详解

id:包含一组数字,表示查询中执行select子句或操作表的顺序

值有以下三种情况

  • id相同,执行顺序由上至下
  • id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
  • id相同不同,同时存在。永远是id大的优先级最高,id相等的时候顺序执行

select_type:表示查询中每个select子句的类型(简单OR复杂)

该字段存在以下的6个值 :