4
4
5
5
在前面[ 《关系型数据库MySQL》] ( ../Day36-40/36-38.关系型数据库MySQL.md ) 一文中,我们已经讲到过索引的相关知识,这里我们做一个简单的回顾。
6
6
7
- 1 . B-Tree索引
8
- 2 . HASH索引
9
- 3 . R-Tree索引(空间索引)
10
- 4 . Full-text索引(全文索引)
7
+ #### 索引的设计原则
11
8
12
- ### 使用过程
9
+ 1 . 创建索引的列并不一定是` select ` 操作中要查询的列,最适合做索引的列是出现在` where ` 子句中经常用作筛选条件或连表子句中作为表连接条件的列。
10
+ 2 . 具有唯一性的列,索引效果好;重复值较多的列,索引效果差。
11
+ 3 . 如果为字符串类型创建索引,最好指定一个前缀长度,创建短索引。短索引可以减少磁盘I/O而且在做比较时性能也更好,更重要的是MySQL底层的高速索引缓存能够缓存更多的键值。
12
+ 4 . 创建一个包含N列的复合索引(多列索引)时,相当于是创建了N个索引,此时应该利用最左前缀进行匹配。
13
+ 5 . 不要过度使用索引。索引并不是越多越好,索引需要占用额外的存储空间而且会影响写操作的性能(插入、删除、更新数据时索引也需要更新)。MySQL在生成执行计划时,要考虑各个索引的使用,这个也是需要耗费时间的。
14
+ 6 . 要注意可能使索引失效的场景,例如:模糊查询使用了前置通配符、使用负向条件进行查询等。
13
15
14
- 过程,通常也称之为存储过程。
16
+ ### 使用过程
15
17
16
- ``` SQL
17
- create procedure ... (params)
18
- begin
19
- ...
20
- end;
18
+ 过程,通常也称之为存储过程,它是事先编译好存储在数据库中的一组SQL的集合。调用存储过程可以简化应用程序开发人员的工作,减少与数据库服务器之间的通信,对于提升数据操作的性能是有帮助的,这些我们在之前的[ 《关系型数据库MySQL》] ( ../Day36-40/36-38.关系型数据库MySQL.md ) 一文中已经提到过。
21
19
22
- call ...
23
- ```
24
20
25
- ``` Python
26
- cursor.callproc(' ...' )
27
- ```
28
21
29
22
### 数据分区
30
23
24
+ MySQL支持做数据分区,通过分区可以存储更多的数据、优化查询,获得更大的吞吐量并快速删除过期的数据。关于这个知识点建议大家看看MySQL的[ 官方文档] ( https://dev.mysql.com/doc/refman/5.7/en/partitioning-overview.html ) 。数据分区有以下几种类型:
25
+
26
+ 1 . RANGE分区:基于连续区间范围,把数据分配到不同的分区。
31
27
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
+ ```
32
60
33
61
### SQL优化
34
62
35
63
1 . 通过` show status ` 了解各种SQL的执行频率。
36
64
37
65
``` SQL
38
- show status like ' com_%' ;
39
- show status like ' innodb_%' ;
40
- show status like ' connections' ;
41
- show status like ' slow_queries' ;
66
+
42
67
```
43
68
44
69
2 . 定位低效率的SQL语句 - 慢查询日志。
@@ -47,26 +72,48 @@ cursor.callproc('...')
47
72
show processlist
48
73
```
49
74
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
+ ```
51
92
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 ` :额外信息。
60
101
61
102
4 . 通过` show profiles ` 和` show profile for query ` 分析SQL。
62
103
63
104
5 . 优化CRUD操作。
64
105
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 ` 禁用排序。
68
114
- 优化嵌套查询
69
115
- 优化or条件
116
+ - 如果条件之间是` or ` 关系,则只有在所有条件都用到索引的情况下索引才会生效。
70
117
- 优化分页查询
71
118
- 使用SQL提示
72
119
- USE INDEX
@@ -75,24 +122,43 @@ cursor.callproc('...')
75
122
76
123
### 配置优化
77
124
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
+
78
144
1 . 调整max_connections
79
145
2 . 调整back_log
80
146
3 . 调整table_open_cache
81
147
4 . 调整thread_cache_size
82
148
5 . 调整innodb_lock_wait_timeout
149
+ 6 . 调整` innodb_buffer_pool_size ` :InnoDB数据和索引的内存缓冲区大小,以字节为单位,这个值设置得越高,访问表数据需要进行的磁盘I/O操作就越少,如果可能甚至可以将该值设置为物理内存大小的80%。
83
150
84
151
### 架构优化
85
152
86
- 1 . 通过拆分提高表的访问效率
153
+ 1 . 通过拆分提高表的访问效率。
87
154
- 垂直拆分
88
155
- 水平拆分
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集群。
98
164
0 commit comments