数据库系列:MySQL慢查询分析和性能优化

from:cnblogs.com/wzh2010/p/17091055.htm

1 背景

我们的业务服务随着功能规模扩大,用户量扩增,流量的不断的增长,经常会遇到一个问题,就是数据存储服务响应变慢。
导致数据库服务变慢的诱因很多,而RD最重要的工作之一就是找到问题并解决问题。
下面以MySQL为例子,我们从几个角度分析可能产生原因,并讨论解决的方案。

2 定位慢查询的原因并优化

2.1 慢查询的分析

开启SlowLog,默认是关闭的,由参数slow_query_log决定,在MySQL命令终端中输入下面的命令:

# 是否开启,这边为开启,默认情况下是off
set global slow_query_log=on;

# 设置慢查询阈值,单位是 s,默认为10s,这边的意思是查询耗时超过0.5s,便会记录到慢查询日志里面
set global long_query_time=0.5;

# 确定慢查询日志的文件名和路径
mysql> show global variables like 'slow_query_log_file';
+---------------------+-------------------------------------------------------+
| Variable_name       | Value                                                 |
+---------------------+-------------------------------------------------------+
| slow_query_log_file | /usr/local/mysql/data/MacintoshdeMacBook-Pro-slow.log |
+---------------------+-------------------------------------------------------+
1 row in set (0.00 sec)

# 检查慢查询的详细指标,可以看到下面 slow_query_log = ON,long_query_time = 0.5 ,都是因为我们调整过的
mysql> show global variables like '%quer%';
+----------------------------------------+-------------------------------------------------------+
| Variable_name                          | Value                                                 |
+----------------------------------------+-------------------------------------------------------+
| binlog_rows_query_log_events           | OFF                                                   |
| ft_query_expansion_limit               | 20                                                    |
| have_query_cache                       | NO                                                    |
| log_queries_not_using_indexes          | OFF                                                   |
| log_throttle_queries_not_using_indexes | 0                                                     |
| long_query_time                        | 0.500000                                             |
| query_alloc_block_size                 | 8192                                                  |
| query_prealloc_size                    | 8192                                                  |
| slow_query_log                         | ON                                                   |
| slow_query_log_file                    | /usr/local/mysql/data/MacintoshdeMacBook-Pro-slow.log |
+----------------------------------------+-------------------------------------------------------+
10 rows in set (0.01 sec)

配置好之后,就会按照阈值默认把慢查询日志收集下来,可以到对应的目录下分析具体的慢请求原因。

2.2 使用Explain进行查询语句分析

2.2.1 分析过程举例

很多时候我们在评审RD同学代码和SQL脚本的时候,上下文和使用环境不了解,不能做出很准确的判断。
这时候使用Explain分析SQL的执行计划就显得非常有用,拿到具体环境中Run一下就能看出很多问题。
举个例子:
模拟一个千万级别的雇员表,我们在没有做索引的字段上做一下查询看看,在500W数据中查询一个名叫LsHfFJA的员工,消耗 2.239S ,获取到一条id为4582071的数据。

再看看他的执行计划,扫描了4952492 条数据才找到该行数据:

mysql> explain select * from emp where empname='LsHfFJA';
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL | 4952492 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
1 row in set

这就是无索引或者索引不合理的结果,这个时候我们就可以根据实际情况进行查询优化了。

2.2.2 Explain需要关注的指标

比较核心要关注的字段一般有 select_type、type、possible_keys、key、rows、Extra等
我们来一个个说明:

select_type的值

解释

SIMPLE

简单查询(不使用关联查询或子查询)

PRIMARY

如果包含关联查询或者子查询,则最外层的查询部分标记primary

UNION

联合查询(UNION)中第二个及后面的查询

DEPENDENT UNION

UNION中的第二个或后面的SELECT语句,取决于外面的查询

UNION RESULT

UNION的结果,union语句中第二个select开始后面所有select

SUBQUERY

字查询中的第一个擦讯

DEPENDENT SUBQUERY

子查询中的第一个查询,并且依赖外部查询

DERIVED

派生表的SELECT, FROM子句的子查询

MATERIALIZED

被物化的子查询

UNCACHEABLE SUBQUERY

一个子查询的结果不能被缓存,必须重新评估外链接的第一行

type的值

解释

system

查询对象表只有一行数据,且只能用于MyISAM和Memory引擎的表,这是最好的情况

const

基于主键或唯一索引查询,最多返回一条结果

eq_ref

类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

fulltext

全文检索

ref_or_null

表连接类型是ref,但进行扫描的索引列中可能包含NULL值

index_merge

利用多个索引

unique_subquery

子查询中使用唯一索引

index_subquery

子查询中使用普通索引

range

只检索给定范围的行,使用一个索引来选择行

index

Full Index Scan,index与ALL区别为index类型只遍历索引树

ALL

Full Table Scan, MySQL将遍历全表以找到匹配的行

表示MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。这个趋向于指导性作用。

显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

3 一些使用上的规范

3.1 分析是否有不合理的查询

★ 以下是我们团队的准入规范,也是CodeReview 标准。

-- 如下,这种查询会导致扫描表:
select a,b,c from t_name where a like '%name';
-- 可以使用%模糊后缀查询如:
select a,b from t_name where a like 'name%';
-- 如 
select a,b,c from t1 limit 10000,20;
-- 优化为:
select a,b,c from t1 where id>10000 limit 20;

3.2 检查是否有不合理的索引使用

建议参考笔者这篇《构建高性能索引(策略篇)》,比较完整

索引必须创建在索引选择性(区分度)较高的列上,选择性的计算方式为:

selecttivity = count(distinct c_name)/count(*) ; 

如果区分度结果小于0.2,则不建议在此列上创建索引,否则大概率会拖慢SQL执行

对于确定需要组成组合索引的多个字段,设计时建议将选择性高的字段靠前放。使用时,组合索引的首字段,必须在where条件中,且需要按照最左前缀规则去匹配。
正确理解和计算索引字段的区分度,文中有计算规则,区分度高的索引,可以快速得定位数据,区分度太低,无法有效的利用索引,可能需要扫描大量数据页,和不使用索引没什么差别。

前缀索引计算公式如下,calcul_len 是数字,长度为1 ~ c_name字段的最长值,可以逐一比较,对比区分度最高的出来
正确理解和计算前缀索引的字段长度,文中有判断规则,合适的长度要保证高的区分度和最恰当的索引存储容量,只有达到最佳状态,才是保证高效率的索引。

select count(distinct left(`c_name`,calcul_len))/count(*) from t_name;
-- 如果建立(depno,empname,job)顺序的索引,job是用不到索引的。
depno=1 and empname>'' and job=1  
PRIMARYKEY (`id`),
UNIQUEKEY `uni_brand_define` (`app_id`,`define_id`)

实际场景中,建议代码交叉评审,当你同事业务代码中的检索语句如下的时候,应建议调整:

select brand_id,brand_name from ds_brand_system where status=? and define_id=? and app_id=?

建议改成如下:

select brand_id,brand_name from ds_brand_system where app_id=? and define_id=? and status=?

虽然说 MySQL的查询优化器会根据实际索引情况进行顺序优化,所以这边不做强制。但是同等条件下还是按照顺序进行排列,比较清晰,并且节省查询优化器的处理。

4 总结

这边仅仅是从查询语句的角度进行分析,实际上缓存服务变慢的可能性很多,不仅仅是慢查询怎么分析(Slow Log、Explain命令)。还应该全面的分析原因,并给出处理方案,如 分析SQL脚本合理性、建立索引或优化索引、读写分离、垂直+水平分区)、多读少写/冷数据 做缓存、优化数据库的锁竞争、数据库配置调优、硬件资源升级 等等,后面几篇我们慢慢说。

展开阅读全文

页面更新:2024-05-08

标签:前缀   字段   语句   函数   索引   效率   性能   条件   类型   建议   数据库   系列   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top