第1章MySQL简介
1.1. 什么是Mysql
- 关系型数据库管理系统。
- 开源,可以定制,采用GPL协议,可以修改源码开发自己的MySQL系统。
- 标准SQL数据语言
- 支持多系统,支持多种语言
- 支持大型数据库,支持5000w条记录数据仓库,32位系统表文件支持4G,64位支持8TG。
1.2. Mysql高手是怎么炼成的
- 数据库内部结构和原理
- 数据库建模优化
- 数据库索引建立
- SQL语句优化
- SQL 编程(自定义函数,存储过程,触发器,定时任务)
- mysql 服务器的安装配置
- 数据性能监控分析与系统优化
- 各种参数常量设定
- 主从复制
- 分布式架构搭建、垂直切割和水平切割
- 数据迁移
- 容灾备份和恢复
- 对开源数据库进行二次开发
2.4.2. 字符集乱码原因
show variables like '%like%'
在/usr/share/mysql/ 中找到 my.cnf 的配置文件,拷贝其中的 my-huge.cnf 到 /etc/ 并命名为 my.cnf 。添加以下内容后再重启服务。
注意:必须将文件拷贝到指定路径,且名称为 my.cnf
[client]
default-character-set=utf8
[mysqld]
character_set_server=utf8
character_set_client=utf8
collation-server=utf8_general_ci
[mysql]
default-character-set=utf8
修改数据库的字符集
mysql> alter database mydb character set 'utf8';
修改数据表的字符集
mysql> alter table mytbl convert to character set 'utf8';
2.5 设置大小写不敏感
查看大小写是否敏感:
show variables like '%lower_case_table_names%'
在 my.cnf 这个配置文件 [mysqld] 中加入 lower_case_table_names = 1 ,然后重启服务器
第3章 MySQL 逻辑架构简介
它的架构在多种不同场景中应用并发挥良好作用,插件式的存储引擎架构查询处理和其他系统任务以及数据存储提取相分离。这种架构可以根据业务需求和实际需求选择适合引擎。
1.1. 连接层
客户端和连接服务,主要完成连接处理、授权认证、及其相关安全方案。
1.2. 服务层
服务名 | 介绍 |
---|---|
Management Serveices & Utilities | 系统管理和控制工具 |
SQL Interface: | SQL 接口。接受用户的 SQL 命令,并且返回用户需要查询的结果。比如 select from就是调用 SQL Interface |
Parser | 解析器。 SQL 命令传递到解析器的时候会被解析器验证和解析 |
Optimizer | 查询优化器。 SQL 语句在查询之前会使用查询优化器对查询进行优化,比如有 where条件时,优化器来决定先投影还是先过滤。 |
Cache 和 Buffer | 查询缓存。如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key 缓存,权限缓存等 |
1.3. 引擎层
存储引擎负责MySQL数据的存储和提取,服务器通过API与存储引擎进行通讯,不同引擎有不同的功能,根据实际需求进行选取。
1.4. 存储层
数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。
2. show profile
利用 show profile 可以查看SQL的执行周期,执行show profiles命令,可以查看最近几次查询。
2.3 大致查询流程
sql的查询流程:
mysql 客户端通过协议与 mysql 服务器建连接,发送查询语句,先检查查询缓存,如果命中,直接返回结果,否则进行语句解析,也就是说,在解析查询之前,服务器会先访问查询缓存(query cache)——它存储 SELECT 语句以及相应的查询结果集。如果某个查询结果已经位于缓存中,服务器就不会再对查询进行解析、优化、以及执行。它仅仅将缓存中的结果返回给用户即可,这将大大提高系统的性能。
语法解析器和预处理:首先 mysql 通过关键字将 SQL 语句进行解析,并生成一颗对应的“解析树”。mysql 解析 器将使用 mysql 语法规则验证和解析查询;预处理器则根据一些 mysql 规则进一步检查解析数是否合法。
查询优化器当解析树被认为是合法的了,并且由优化器将其转化成执行计划。一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。。
然后,mysql 默认使用的 BTREE 索引,并且一个大致方向是:无论怎么折腾 sql,至少在目前来说,mysql 最多只
用到表中的一个索引。
2.4 SQL 的执行顺序
手写的顺序:
真正执行的顺序:
随着 Mysql 版本的更新换代,其优化器也在不断的升级,优化器会分析不同执行顺序产生的性能消耗不同而动
态调整执行顺序。下面是经常出现的查询顺序:
2.5 MyISAM 和 和 InnoDB
对比项 | MyISAM 名 | InnoDB |
---|---|---|
外键 | 不支持 | 支持 |
事务 | 不支持 | 支持 |
行表锁 | 表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作 | 行锁,操作时只锁某一行,不对其它行有影响,适合高并发的操作 |
缓存 | 只缓存索引,不缓存真实数据 | 不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响 |
关注点 | 读性能 | 并发写、事务、资源 |
默认安装 | Y | Y |
默认使用 | N | Y |
自 带 系 统 表使用 | Y | N |
第4章 SQL预热
1. 常见的 Join 查询图
我们在学些左连接、右连接、内连接之前必须知道,分清左右表,from 后面都是 左表 ,join为右表。
参考
左连接: 是以左表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将左表所有的查询信息列出,而右表只列出ON后条件与左表满足的部分。
SELECT * FROM Table A LEFT JOIN Table B ON A.id = B.deptId;
右连接: 右连接的定义,是以右表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将右表所有的查询信息列出,而左表只列出ON后条件与右表满足的部分。右连接全称为右外连接,是外连接的一种;
SELECT * FROM Table A RIGHT JOIN Table B ON A.id = B.deptId;
内链接(自连接): 使用比较运算符根据每个表共有的列的值匹配两个表中的行;
SELECT * FROM Table A INNER JOIN Table B ON A.id = B.deptId;
第5章 索引优化分析
5.1. 概念
索引是数据结构,排好序的快速查找数据结构。数据结构以某种方式引用(指向)数据。
左边蓝色是2列的数据表,最左边是物理地址,为了加快col2查找,右边是二叉查找树,每个节点包含索引值和对应数据记录的物理地址。
5.1.2 优缺点
优点:
- 提高数据查找效率,降低数据库IO成本。
- 通过索引对数据排序,降低排序成本,较低CPU消耗。
缺点:
- 虽然查询速度提高,同时降低更新表速度,如对表insert、update、delete,如果对索引列修改,必然导致索引信息改变。
- 索引本身也是表,记录主键和索引列字段,指向实体表的记录,且占用空间。
5.2 Mysql的索引
MySQL 使用的是 Btree 索引。
一颗 b 树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如 17、35 并不真实存在于数据表中。
真实的情况是,3 层的 b+树可以表示上百万的数据,如果上百万的数据查找只需要三次 IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次 IO,那么总共需要百万次的 IO,显然成本非常非常高。
5.2.2. B+tree 索引
5.3. MySQL索引分类
5.3.1. 单值索引
一个索引只包含单个列,一个表可以有多个单列索引。
//单独建单值索引
CREATE INDEX idx_customer_name ON customer(customer_name);
5.3.2. 唯一索引
索引列必须是唯一(身份证号,手机号),允许为空值。
//单独建唯一索引
CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);
5.3.3.主键索引
设定为主键后数据库会自动建立索引,innodb为聚簇索引。
5.3.4. 复合索引
一个索引包含多个列
5.4. 索引的创建时机
适合创建索引的情况
- 主键自动建立唯一索引。
- 频繁作为查询条件的字段。
- 查询中与其他表关联的字段,外键关系建立索引
- 单键/组合索引的选择问题,组合索引性价比高
- 查询排序字段
- 查询统计和分组字段
不适合创建索引的情况
- 表记录少
- 经常增删改字段
- where条件用不到
- 过滤不好不适合建立索引
第6章 Explain性能分析
分析查询语句或者表结构的性能瓶颈,Explain+SQL语句:
id
- id相同,执行顺序由上往下
- id不同,id值越大优先级越高,越先被执行,如果是子查询,id会增加。
- id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id 值越大,优先级越高,越先执行衍生 = DERIVED
id 号每个号码,表示一趟独立查询,一个sql查询趟数越少越好。
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 |
SIMPLE
SIMPLE 代表单表查询:PRIMARY
查询中若包含任何复杂的子部分,最外层查询则被标记为 Primary。DERIVED
在 FROM 列表中包含的子查询被标记为 DERIVED(衍生),MySQL 会递归执行这些子查询, 把结果放在临时表里。SUBQUERY
在 SELECT 或 WHERE 列表中包含了子查询。DEPENDENT SUBQUERY
在SELECT 或 WHERE 列表中包含了子查询,子查询基于外层。
UNCACHEABLE SUBQUREY
当使用了@@来引用系统变量的时候,不会使用缓存。
UNION
若第二个 SELECT 出现在 UNION 之后,则被标记为 UNION;若 UNION 包含在 FROM 子句的子查询中,外层 SELECT 将被标记为:DERIVED。UNION RESULT
从 UNION 表获取结果的 SELECT。
6.5 table
这个数据是基于哪张表的。
6.6 type
type 是查询的访问类型(《高性能mysql》称呼为“访问类型”)。是较为重要的一个指标,结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >unique_subquery > index_subquery > range > index >ALL,一般来说,得保证查询至少达到 range 级别,最好能达到 ref。
6.6.1 system
表只有一行记录(等于系统表),这是 const 类型的特列,平时不会出现,这个也可以忽略不计
6.6.2 const
表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引。因为只匹配一行数据,所以很快如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量。
where 单个条件如 id =1,且id是主键或者unique索引时候,才是const。
6.6.3 eq_ref
唯一性索引(此字段内容必须是唯一的)扫描,where t.id = a.id 后面表中只有一条记录匹配,常见于主键或唯一索引扫描。6.6.4 ref
非唯一索引扫描,返回匹配某个单独值的所有行数据。
建立索引:
6.6.5 range
只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的 where 语句中出现了 between、<、>、in 等的查询这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。6.6.6 index
出现index是sql使用了索引但是没用通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组。6.6.7 all
全表扫描总结:以上常用类型system>const>eq_ref>ref>range>index
system:一个表只有一行
const:前提是索引一次找到,where 主键或者唯一索引
eq_ref:当前字段关联其他表,且唯一一行,where a.id=b.id,主键或者唯一索引
ref:当前字段关联其他表,存在多行对应
6.7 possible_keys
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出, 但不一定被查询实际使用。
6.8 key
实际使用的索引。如果为NULL,则没有使用索引。
6.9 key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。 key_len 字段能够帮你检查是否充分的利用上了索引。ken_len 越长,说明索引使用的越充分。6.10 ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。6.11 rows
rows 列显示 MySQL 认为它执行查询时必须检查的行数。越少越好!6.12 Extra
其他的额外重要的信息。
6.12.1Using filesort
说明 mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL 中无法利用索引完成的排序操作称为“文件排序”。优化后,不再出现 filesort 的情况:
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度。
6.12.2 Using temporary
使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
优化前:
6.12.3 Using index
Using index 代表表示相应的 select 操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!如果同时出现 using where,表明索引被用来执行索引键值的查找;如果没有同时出现 using where,表明索引只是用来读取数据而非利用索引执行查找。
利用索引进行了排序或分组。
6.12.5 Using join buffer
使用了连接缓存。
6.12.7
在没有 GROUPBY 子句的情况下,基于索引优化 MIN/MAX 操作或者对于 MyISAM 存储引擎优化 COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。