Skip to content

Commit 9fdf387

Browse files
committed
更新了第93天的文档
1 parent a2e0400 commit 9fdf387

File tree

1 file changed

+108
-42
lines changed

1 file changed

+108
-42
lines changed

Day91-100/93.MySQL性能优化.md

Lines changed: 108 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,66 @@
44

55
在前面[《关系型数据库MySQL》](../Day36-40/36-38.关系型数据库MySQL.md)一文中,我们已经讲到过索引的相关知识,这里我们做一个简单的回顾。
66

7-
1. B-Tree索引
8-
2. HASH索引
9-
3. R-Tree索引(空间索引)
10-
4. Full-text索引(全文索引)
7+
#### 索引的设计原则
118

12-
### 使用过程
9+
1. 创建索引的列并不一定是`select`操作中要查询的列,最适合做索引的列是出现在`where`子句中经常用作筛选条件或连表子句中作为表连接条件的列。
10+
2. 具有唯一性的列,索引效果好;重复值较多的列,索引效果差。
11+
3. 如果为字符串类型创建索引,最好指定一个前缀长度,创建短索引。短索引可以减少磁盘I/O而且在做比较时性能也更好,更重要的是MySQL底层的高速索引缓存能够缓存更多的键值。
12+
4. 创建一个包含N列的复合索引(多列索引)时,相当于是创建了N个索引,此时应该利用最左前缀进行匹配。
13+
5. 不要过度使用索引。索引并不是越多越好,索引需要占用额外的存储空间而且会影响写操作的性能(插入、删除、更新数据时索引也需要更新)。MySQL在生成执行计划时,要考虑各个索引的使用,这个也是需要耗费时间的。
14+
6. 要注意可能使索引失效的场景,例如:模糊查询使用了前置通配符、使用负向条件进行查询等。
1315

14-
过程,通常也称之为存储过程。
16+
### 使用过程
1517

16-
```SQL
17-
create procedure ... (params)
18-
begin
19-
...
20-
end;
18+
过程,通常也称之为存储过程,它是事先编译好存储在数据库中的一组SQL的集合。调用存储过程可以简化应用程序开发人员的工作,减少与数据库服务器之间的通信,对于提升数据操作的性能是有帮助的,这些我们在之前的[《关系型数据库MySQL》](../Day36-40/36-38.关系型数据库MySQL.md)一文中已经提到过。
2119

22-
call ...
23-
```
2420

25-
```Python
26-
cursor.callproc('...')
27-
```
2821

2922
### 数据分区
3023

24+
MySQL支持做数据分区,通过分区可以存储更多的数据、优化查询,获得更大的吞吐量并快速删除过期的数据。关于这个知识点建议大家看看MySQL的[官方文档](https://dev.mysql.com/doc/refman/5.7/en/partitioning-overview.html)。数据分区有以下几种类型:
25+
26+
1. RANGE分区:基于连续区间范围,把数据分配到不同的分区。
3127

28+
```SQL
29+
CREATE TABLE tb_emp (
30+
eno INT NOT NULL,
31+
ename VARCHAR(20) NOT NULL,
32+
job VARCHAR(10) NOT NULL,
33+
hiredate DATE NOT NULL,
34+
dno INT NOT NULL
35+
)
36+
PARTITION BY RANGE( YEAR(hiredate) ) (
37+
PARTITION p0 VALUES LESS THAN (1960),
38+
PARTITION p1 VALUES LESS THAN (1970),
39+
PARTITION p2 VALUES LESS THAN (1980),
40+
PARTITION p3 VALUES LESS THAN (1990),
41+
PARTITION p4 VALUES LESS THAN MAXVALUE
42+
);
43+
```
44+
45+
2. LIST分区:基于枚举值的范围,把数据分配到不同的分区。
46+
47+
3. HASH分区 / KEY分区:基于分区个数,把数据分配到不同的分区。
48+
49+
```SQL
50+
CREATE TABLE tb_emp (
51+
eno INT NOT NULL,
52+
ename VARCHAR(20) NOT NULL,
53+
job VARCHAR(10) NOT NULL,
54+
hiredate DATE NOT NULL,
55+
dno INT NOT NULL
56+
)
57+
PARTITION BY HASH(dno)
58+
PARTITIONS 4;
59+
```
3260

3361
### SQL优化
3462

3563
1. 通过`show status`了解各种SQL的执行频率。
3664

3765
```SQL
38-
show status like 'com_%';
39-
show status like 'innodb_%';
40-
show status like 'connections';
41-
show status like 'slow_queries';
66+
4267
```
4368

4469
2. 定位低效率的SQL语句 - 慢查询日志。
@@ -47,26 +72,48 @@ cursor.callproc('...')
4772
show processlist
4873
```
4974

50-
3. 通过`explain`了解SQL的执行计划。
75+
3. 通过`explain`了解SQL的执行计划。例如:
76+
77+
```SQL
78+
explain select ename, job, sal from tb_emp where dno=20\G
79+
*************************** 1. row ***************************
80+
id: 1
81+
select_type: SIMPLE
82+
table: tb_emp
83+
type: ref
84+
possible_keys: fk_emp_dno
85+
key: fk_emp_dno
86+
key_len: 5
87+
ref: const
88+
rows: 7
89+
Extra: NULL
90+
1 row in set (0.00 sec)
91+
```
5192

52-
- select_type:查询类型(simple、primary、union、subquery)
53-
- table:输出结果集的表
54-
- type:访问类型(ALL、index、range、ref、eq_ref、const、NULL)
55-
- possible_keys:查询时可能用到的索引
56-
- key:实际使用的索引
57-
- key_len:索引字段的长度
58-
- rows:扫描的行数
59-
- extra:额外信息
93+
- `select_type`:查询类型(SIMPLE - 简单查询、PRIMARY - 主查询、UNION - 并集、SUBQUERY - 子查询)。
94+
- `table`:输出结果集的表
95+
- `type`:访问类型(ALL - 全表查询性能最差、index、range、ref、eq_ref、const、NULL)
96+
- `possible_keys`:查询时可能用到的索引
97+
- `key`:实际使用的索引
98+
- `key_len`:索引字段的长度
99+
- `rows`:扫描的行数,行数越少肯定性能越好。
100+
- `extra`:额外信息
60101

61102
4. 通过`show profiles``show profile for query`分析SQL。
62103

63104
5. 优化CRUD操作。
64105

65-
- 优化insert语句
66-
- 优化order by语句
67-
- 优化group by语句
106+
- 优化`insert`语句
107+
-`insert`语句后面跟上多组值进行插入在性能上优于分开`insert`
108+
- 如果有多个连接向同一个表插入数据,使用`insert delayed`可以获得更好的性能。
109+
- 如果要从一个文本文件装载数据到表时,使用`load data infile``insert`性能好得多。
110+
- 优化`order by`语句
111+
- 如果`where`子句的条件和`order by`子句的条件相同,而且排序的顺序与索引的顺序相同,如果还同时满足排序字段都是升序或者降序,那么只靠索引就能完成排序。
112+
- 优化`group by`语句
113+
- 在使用`group by`子句分组时,如果希望避免排序带来的开销,可以用`order by null`禁用排序。
68114
- 优化嵌套查询
69115
- 优化or条件
116+
- 如果条件之间是`or`关系,则只有在所有条件都用到索引的情况下索引才会生效。
70117
- 优化分页查询
71118
- 使用SQL提示
72119
- USE INDEX
@@ -75,24 +122,43 @@ cursor.callproc('...')
75122

76123
### 配置优化
77124

125+
可以使用下面的命令来查看MySQL服务器配置参数的默认值。
126+
127+
```SQL
128+
show variables;
129+
show variables like 'key_%';
130+
show variables like '%cache%';
131+
show variables like 'innodb_buffer_pool_size';
132+
```
133+
134+
通过下面的命令可以了解MySQL服务器运行状态值。
135+
136+
```SQL
137+
show status;
138+
show status like 'com_%';
139+
show status like 'innodb_%';
140+
show status like 'connections';
141+
show status like 'slow_queries';
142+
```
143+
78144
1. 调整max_connections
79145
2. 调整back_log
80146
3. 调整table_open_cache
81147
4. 调整thread_cache_size
82148
5. 调整innodb_lock_wait_timeout
149+
6. 调整`innodb_buffer_pool_size`:InnoDB数据和索引的内存缓冲区大小,以字节为单位,这个值设置得越高,访问表数据需要进行的磁盘I/O操作就越少,如果可能甚至可以将该值设置为物理内存大小的80%。
83150

84151
### 架构优化
85152

86-
1. 通过拆分提高表的访问效率
153+
1. 通过拆分提高表的访问效率
87154
- 垂直拆分
88155
- 水平拆分
89-
2. 逆范式理论
90-
- 数据表设计的规范程度称之为范式(Normal Form)
91-
- 1NF:列不能再拆分
92-
- 2NF:所有的属性都依赖于主键
93-
- 3NF:所有的属性都直接依赖于主键(消除传递依赖)
94-
- BCNF:消除非平凡多值依赖
95-
3. 使用中间表提高统计查询速度
96-
4. 主从复制和读写分离
97-
5. 配置MySQL集群
156+
2. 逆范式理论。数据表设计的规范程度称之为范式(Normal Form),要提升表的规范程度通常需要将大表拆分为更小的表,范式级别越高数据冗余越小,而且在插入、删除、更新数据时出问题的可能性会大幅度降低,但是节省了空间就意味着查询数据时可能花费更多的时间,原来的单表查询可能会变成连表查询。为此,项目实践中我们通常会进行逆范式操作,故意降低范式级别增加冗余来减少查询的时间开销。
157+
- 1NF:列不能再拆分
158+
- 2NF:所有的属性都依赖于主键
159+
- 3NF:所有的属性都直接依赖于主键(消除传递依赖)
160+
- BCNF:消除非平凡多值依赖
161+
3. 使用中间表提高统计查询速度。
162+
4. 主从复制和读写分离,具体内容请参考[《项目部署上线和性能调优》](./98.项目部署上线和性能调优.md)
163+
5. 配置MySQL集群。
98164

0 commit comments

Comments
 (0)