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
35631 . 通过` 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
44692 . 定位低效率的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
611024 . 通过` show profiles ` 和` show profile for query ` 分析SQL。
62103
631045 . 优化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+
781441 . 调整max_connections
791452 . 调整back_log
801463 . 调整table_open_cache
811474 . 调整thread_cache_size
821485 . 调整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