更新了第93天文档内容

pull/351/head
jackfrued 2019-10-28 01:18:11 +08:00
parent 04e21ddedf
commit b27a53fe40
1 changed files with 93 additions and 10 deletions

View File

@ -70,7 +70,7 @@ MySQL支持做数据分区通过分区可以存储更多的数据、优化查
| slow_query_log | OFF | | slow_query_log | OFF |
| slow_query_log_file | /mysql/data/localhost-slow.log | | slow_query_log_file | /mysql/data/localhost-slow.log |
+---------------------------+----------------------------------+ +---------------------------+----------------------------------+
mysql> show variables like 'long_query_time'; mysql> show variables like 'long_query_time';
+-----------------+-----------+ +-----------------+-----------+
| Variable_name | Value | | Variable_name | Value |
@ -124,24 +124,99 @@ MySQL支持做数据分区通过分区可以存储更多的数据、优化查
3. 通过`show profiles`和`show profile for query`分析SQL。 3. 通过`show profiles`和`show profile for query`分析SQL。
MySQL从5.0.37开始支持剖面系统来帮助用户了解SQL执行性能的细节可以通过下面的方式来查看MySQL是否支持和开启了剖面系统。
```SQL
select @@have_profiling;
select @@profiling;
```
如果没有开启剖面系统可以通过下面的SQL来打开它。
```SQL
set profiling=1;
```
接下来就可以通过剖面系统来了解SQL的执行性能例如
```SQL
mysql> select count(*) from tb_emp;
+----------+
| count(*) |
+----------+
| 14 |
+----------+
1 row in set (0.00 sec)
mysql> show profiles;
+----------+------------+-----------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------+
| 1 | 0.00029600 | select count(*) from tb_emp |
+----------+------------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> show profile for query 1;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000076 |
| checking permissions | 0.000007 |
| Opening tables | 0.000016 |
| init | 0.000013 |
| System lock | 0.000007 |
| optimizing | 0.000005 |
| statistics | 0.000012 |
| preparing | 0.000010 |
| executing | 0.000003 |
| Sending data | 0.000070 |
| end | 0.000012 |
| query end | 0.000008 |
| closing tables | 0.000012 |
| freeing items | 0.000032 |
| cleaning up | 0.000013 |
+----------------------+----------+
15 rows in set, 1 warning (0.00 sec)
```
4. 优化CRUD操作。 4. 优化CRUD操作。
- 优化`insert`语句 - 优化`insert`语句
- 在`insert`语句后面跟上多组值进行插入在性能上优于分开`insert`。 - 在`insert`语句后面跟上多组值进行插入在性能上优于分开`insert`。
- 如果有多个连接向同一个表插入数据,使用`insert delayed`可以获得更好的性能。 - 如果有多个连接向同一个表插入数据,使用`insert delayed`可以获得更好的性能。
- 如果要从一个文本文件装载数据到表时,使用`load data infile`比`insert`性能好得多。 - 如果要从一个文本文件装载数据到表时,使用`load data infile`比`insert`性能好得多。
- 优化`order by`语句 - 优化`order by`语句
- 如果`where`子句的条件和`order by`子句的条件相同,而且排序的顺序与索引的顺序相同,如果还同时满足排序字段都是升序或者降序,那么只靠索引就能完成排序。 - 如果`where`子句的条件和`order by`子句的条件相同,而且排序的顺序与索引的顺序相同,如果还同时满足排序字段都是升序或者降序,那么只靠索引就能完成排序。
- 优化`group by`语句 - 优化`group by`语句
- 在使用`group by`子句分组时,如果希望避免排序带来的开销,可以用`order by null`禁用排序。 - 在使用`group by`子句分组时,如果希望避免排序带来的开销,可以用`order by null`禁用排序。
- 优化嵌套查询 - 优化嵌套查询
- MySQL从4.1开始支持嵌套查询子查询这使得可以将一个查询的结果当做另一个查询的一部分来使用。在某些情况下子查询可以被更有效率的连接查询取代因为在连接查询时MySQL不需要在内存中创建临时表来完成这个逻辑上需要多个步骤才能完成的查询。
- 优化or条件 - 优化or条件
- 如果条件之间是`or`关系,则只有在所有条件都用到索引的情况下索引才会生效。 - 如果条件之间是`or`关系,则只有在所有条件都用到索引的情况下索引才会生效。
- 优化分页查询 - 优化分页查询
- 分页查询时,一个比较头疼的事情是如同`limit 1000, 20`此时MySQL已经排序出前1020条记录但是仅仅返回第1001到1020条记录前1000条实际都用不上查询和排序的代价非常高。一种常见的优化思路是在索引上完成排序和分页的操作然后根据返回的结果做表连接操作来得到最终的结果这样可以避免出现全表查询也避免了外部排序。
```SQL
select * from tb_emp order by ename limit 1000, 20;
select * from tb_emp t1 inner join (select eno from tb_emp order by ename limit 1000, 20) t2 on t1.eno=t2.eno;
```
上面的代码中第2行SQL是优于第1行SQL的当然我们的前提是已经在`ename`字段上创建了索引。
- 使用SQL提示 - 使用SQL提示
- USE INDEX - USE INDEX建议MySQL使用指定的索引。
- IGNORE INDEX - IGNORE INDEX建议MySQL忽略掉指定的索引。
- FORCE INDEX - FORCE INDEX强制MySQL使用指定的索引。
### 配置优化 ### 配置优化
@ -164,24 +239,32 @@ show status like 'connections';
show status like 'slow_queries'; show status like 'slow_queries';
``` ```
1. 调整max_connections 1. 调整`max_connections`MySQL最大连接数量默认151。在Linux系统上如果内存足够且不考虑用户等待响应时间这些问题MySQL理论上可以支持到万级连接但是通常情况下这个值建议控制在1000以内。
2. 调整back_log 2. 调整`back_log`TCP连接的积压请求队列大小通常是max_connections的五分之一最大不能超过900。
3. 调整table_open_cache 3. 调整`table_open_cache`这个值应该设置为max_connections的N倍其中N代表每个连接在查询时打开的表的最大个数。
4. 调整thread_cache_size 4. 调整`innodb_lock_wait_timeout`该参数可以控制InnoDB事务等待行锁的时间默认值是50ms对于反馈响应要求较高的应用可以将这个值调小避免事务长时间挂起对于后台任务可以将这个值调大来避免发生大的回滚操作。
5. 调整innodb_lock_wait_timeout 5. 调整`innodb_buffer_pool_size`InnoDB数据和索引的内存缓冲区大小以字节为单位这个值设置得越高访问表数据需要进行的磁盘I/O操作就越少如果可能甚至可以将该值设置为物理内存大小的80%。
6. 调整`innodb_buffer_pool_size`InnoDB数据和索引的内存缓冲区大小以字节为单位这个值设置得越高访问表数据需要进行的磁盘I/O操作就越少如果可能甚至可以将该值设置为物理内存大小的80%。
### 架构优化 ### 架构优化
1. 通过拆分提高表的访问效率。 1. 通过拆分提高表的访问效率。
- 垂直拆分 - 垂直拆分
- 水平拆分 - 水平拆分
2. 逆范式理论。数据表设计的规范程度称之为范式Normal Form要提升表的规范程度通常需要将大表拆分为更小的表范式级别越高数据冗余越小而且在插入、删除、更新数据时出问题的可能性会大幅度降低但是节省了空间就意味着查询数据时可能花费更多的时间原来的单表查询可能会变成连表查询。为此项目实践中我们通常会进行逆范式操作故意降低范式级别增加冗余来减少查询的时间开销。 2. 逆范式理论。数据表设计的规范程度称之为范式Normal Form要提升表的规范程度通常需要将大表拆分为更小的表范式级别越高数据冗余越小而且在插入、删除、更新数据时出问题的可能性会大幅度降低但是节省了空间就意味着查询数据时可能花费更多的时间原来的单表查询可能会变成连表查询。为此项目实践中我们通常会进行逆范式操作故意降低范式级别增加冗余来减少查询的时间开销。
- 1NF列不能再拆分 - 1NF列不能再拆分
- 2NF所有的属性都依赖于主键 - 2NF所有的属性都依赖于主键
- 3NF所有的属性都直接依赖于主键消除传递依赖 - 3NF所有的属性都直接依赖于主键消除传递依赖
- BCNF消除非平凡多值依赖 - BCNF消除非平凡多值依赖
3. 使用中间表提高统计查询速度。 3. 使用中间表提高统计查询速度。
使用`insert into 中间表 select ... where ...`这样的语句先将需要的数据筛选出来放到中间表中,然后再对中间表进行统计,避免不必要的运算和处理。
4. 主从复制和读写分离,具体内容请参考[《项目部署上线和性能调优》](./98.项目部署上线和性能调优.md)。 4. 主从复制和读写分离,具体内容请参考[《项目部署上线和性能调优》](./98.项目部署上线和性能调优.md)。
5. 配置MySQL集群。 5. 配置MySQL集群。
> **说明**本章内容参考了网易出品的《深入浅出MySQL》一书该书和《高性能MySQL》一样都对MySQL进行了深入细致的讲解虽然总体感觉后者更加高屋建瓴但是前者也算得上是提升MySQL技能的佳作作者的文字功底稍显粗糙深度也不及后者建议有兴趣的读者可以阅读这两本书。