From c16304f457b6a099189265b07b4330d3f44eef5d Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 26 May 2018 10:17:37 +0800 Subject: [PATCH] auto commit --- notes/MySQL.md | 85 +++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/notes/MySQL.md b/notes/MySQL.md index 51e7e745..5edae271 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -14,12 +14,14 @@ * [索引优化](#索引优化) * [B-Tree 和 B+Tree 原理](#b-tree-和-btree-原理) * [四、查询性能优化](#四查询性能优化) + * [使用 Explain 进行分析](#使用-explain-进行分析) + * [优化数据访问](#优化数据访问) + * [重构查询方式](#重构查询方式) * [五、切分](#五切分) * [垂直切分](#垂直切分) * [水平切分](#水平切分) * [切分的选择](#切分的选择) * [存在的问题](#存在的问题) -* [六、故障转移和故障恢复](#六故障转移和故障恢复) * [参考资料](#参考资料) @@ -303,35 +305,43 @@ B+Tree 相比于 B-Tree 更适合外存索引,因为 B+Tree 内节点去掉了 # 四、查询性能优化 -### Explain +## 使用 Explain 进行分析 -用来分析 SQL 语句,分析结果中比较重要的字段有: +Explain 用来分析 SELECT 查询语句,开发人员可以通过分析结果来优化查询语句。 -- select_type : 查询类型,有简单查询、联合查询和子查询 +比较重要的字段有: +- select_type : 查询类型,有简单查询、联合查询、子查询等 - key : 使用的索引 - - rows : 扫描的行数 -### 减少返回的列 +更多内容请参考:[MySQL 性能优化神器 Explain 使用分析](https://segmentfault.com/a/1190000008131735) -慢查询主要是因为访问了过多数据,除了访问过多行之外,也包括访问过多列。 +## 优化数据访问 -最好不要使用 SELECT * 语句,要根据需要选择查询的列。 +### 1. 减少请求的数据量 -### 减少返回的行 +**(一)只返回必要的列** -最好使用 LIMIT 语句来取出想要的那些行。 +最好不要使用 SELECT * 语句。 -还可以建立索引来减少条件语句的全表扫描。例如对于下面的语句,不使用索引的情况下需要进行全表扫描,而使用索引只需要扫描几行记录即可,使用 Explain 语句可以通过观察 rows 字段来看出这种差异。 +**(二)只返回必要的行** -```sql -SELECT * FROM sakila.film_actor WHERE film_id = 1; -``` +使用 WHERE 语句进行查询过滤,有时候也需要使用 LIMIT 语句来限制返回的数据。 -### 拆分大的 DELETE 或 INSERT 语句 +**(三)缓存重复查询的数据** -如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。 +使用缓存可以避免在数据库中进行查询,特别要查询的数据经常被重复查询,缓存可以带来的查询性能提升将会是非常明显的。 + +### 2. 减少服务器端扫描的行数 + +最有效的方式是使用索引来覆盖查询。 + +## 重构查询方式 + +### 1. 切分大查询 + +一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。 ```sql DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); @@ -345,6 +355,29 @@ do { } while rows_affected > 0 ``` +### 2. 分解关联查询 + +将一个关联查询分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有: + +- 让缓存更高效。对于关联查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。 +- 减少锁竞争; +- 在应用层进行关联,可以更容易对数据库进行拆分,从而更容易做到高性能和可扩展。 +- 查询本身效率也可能会有所提升。例如下面的例子中,使用 IN() 代替关联查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的关联要更高效。 +- 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。 + +```sql +SELECT * FROM tab +JOIN tag_post ON tag_post.tag_id=tag.id +JOIN post ON tag_post.post_id=post.id +WHERE tag.tag='mysql'; +``` + +```sql +SELECT * FROM tag WHERE tag='mysql'; +SELECT * FROM tag_post WHERE tag_id=1234; +SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904); +``` + # 五、切分 @@ -378,26 +411,6 @@ do { 最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算。 -# 六、故障转移和故障恢复 - -故障转移也叫做切换,当主库出现故障时就切换到备库,使备库成为主库。故障恢复顾名思义就是从故障中恢复过来,并且保证数据的正确性。 - -### 提升备库或切换角色 - -提升一台备库为主库,或者在一个主-主复制结构中调整主动和被动角色。 - -### 虚拟 IP 地址和 IP 托管 - -为 MySQL 实例指定一个逻辑 IP 地址,当 MySQL 实例失效时,可以将 IP 地址转移到另一台 MySQL 服务器上。 - -### 中间件解决方案 - -通过代理,可以路由流量到可以使用的服务器上。 - -### 在应用中处理故障转移 - -将故障转移整合到应用中可能导致应用变得太过笨拙。 - # 参考资料 - BaronScbwartz, PeterZaitsev, VadimTkacbenko, 等. 高性能 MySQL[M]. 电子工业出版社, 2013.