数据库优化 学习笔记
一、影响服务器性能的几个方面
1.1、影响因素
-
服务器硬件
-
服务器的操作系统
-
数据库存储引擎的选择
-
数据库参数配置
-
数据库结构设计和SQL语句
1.2、SQL 性能下降原因
-
查询语句写的不好
-
索引失效
-
关联查询太多 join
-
服务器调优及各个参数设置
1.3、SQL 加载顺序
手写 SQL 的顺序 ≠ 机读的 SQL 顺序
- 手写SQL的顺序
select
distinct <select _list>
from <left_table>
join <right_table> on <join_codition>
where <where_condition>
group by <group_by_list>
having <having_condition>
order by <order_by_condition>
limit <limit number>
- 机读的SQL顺序
from <left_table>
on <join_codition>
<right_type> join <right_table>
where <where_condition>
group by <group_by_list>
having <having_condition>
select
distinct <select _list>
order by <order_by_condition>
limit <limit number>
1.4、MySQL常见瓶颈
-
CPU: CPU 在饱和的时候一般发生在数据装入内存或从磁盘读取数据的时候。
-
IO: 磁盘 I/O 瓶颈发生在装入数据远大于内存容量的时候。
-
服务器硬件的性能瓶颈。
二、explain 分析 SQL
2.1、explain 是什么?
使用 explain 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。
2.2、explain 能干嘛?
-
查看执行该 SQL 语句表的读取顺序
-
查看执行该 SQL 语句数据读取操作的操作类型
-
查看执行该 SQL 语句哪些索引可以使用
-
查看执行该 SQL 语句哪些索引被实际使用
-
查看执行该 SQL 语句表之间的引用
-
查看执行该 SQL 语句每张表有多少行被优化器查询
2.3、explain 怎么玩?
-- explain + SQL 语句
-- 如:
explain select * from test;
三、explain 字段解释
3.1、id —— 表的读取顺序(需关注)
select 查询顺序号,包含一组数字,表示查询中执行 select 字句或操作表的顺序。有两种情况:
- id 相同,执行顺序由上至下;
- id 不同,如果是子查询,id 的序号会递增,id 值越大则优先级越高越先被执行。
3.2、select_type —— 数据读取操作的操作类型
-
simple: 简单的 select 查询,查询中不包含子查询 或者 union
-
primary: 查询中若包含任何复杂的子部分,最外层查询则被标记。就是最后加载的那个,执行顺序排最后的那个表的 select_type 为 primary
-
subquery: 在 select 或 where 列表中包含了子查询
-
union: 若第二个 select 出现在 union 之后,则被标记为 union ,
union 简单使用:select * from t1 union select * from t4
-
union result: 从 union 表获取结果的 select
3.3、table —— 显示这一行的数据是关于那张表的
3.4、partitions —— 查询访问的分区
3.5、type —— 可获知 sql 语句的执行效率(很重要)
从最好到最差依次是:
-- system 和 const 都是不太现实的
system > const > eq_ref > ref > range > index > ALL
-
system: 表只有一行记录(等于系统表),这是 const 类型的特例
-
const: 表示通过索引一次就找到了,const 用于比较 primary key
-
eq_ref: 唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配
-
ref: 非唯一性索引扫描,返回匹配某个单独值得所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行
-
range: 只检索给定范围的行,使用一个索引来选择行
-
index: Full Index Scan,index 与 ALL区别为 index 类型只遍历索引树
-
ALL: 将遍历全表找到匹配的行(查询的时候尽量不要用
select *
,否则很可能就是 ALL)
3.6、possible_keys —— 显示可能应用在这张表中的索引(一个或多个)
3.7、key —— 实际使用到的索引(需关注注)
-
执行该 SQL 语句时,实际使用的索引。如果为null,则没有使用索引。
-
若查询的表中存在复合索引和主键索引,则 key 列表中显示复合索引。
3.8、key_len —— 索引长度
-
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好
-
key_len 显示的值为索引字段的最大可能长度,并非实际使用长度,即 key_len 是根据表定义计算而得,不是通过表内检索出的
索引长度计算(了解)
varchr(24)变长字段且允许NULL
24*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
--例: varchr(24)变长字段且允许NULL, 编码为 utf8,
--则 key_len = 24 * 3 + 1 + 2
varchr(10)变长字段且不允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)+2(变长字段)
char(10)固定字段且允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)
char(10)固定字段且不允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)
3.9、ref —— 显示索引相应表的哪一列被使用到了
3.10、rows
- 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
3.11、Extra —— 包含不适合在其他列中显示但十分重要的额外信息(重点关注下面的前两个)
-
Using filesort: 说明 mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,MySQL 中无法利用索引完成的排序操作称为 " 文件内排序 "。
若 Extra 中出现这个,那么说明 SQL 语句必须做优化了。 -
Using temporary: 使用 临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。(查询时创建临时表 → 结果存放在临时表中 → 查询结束删除临时表)
若出现这个, SQL 语句也要优化了。(表太长,可以在语句后面加“\G”不用分号,改变显示形式)
-
Using index: 使用了索引,避免了全表扫描。
-
Using where: 使用了 where 过滤。
-
Using join buffer: 使用了连接缓存。
-
impossible where: 不可能的条件,where 子句的值总是 false。