MySql 优化详解(一)EXPLAIN分析
2017-12-25 17:57
956 查看
MySql 优化详解(一)EXPLAIN分析
慢 SQL 的定义
慢sql在广义上指执行速度很慢的
sql语句,具体指查询时间大于指定慢查询时间的查询
查看设置的慢查询时间
show variables like ‘long_query_time’;
修改慢查询的时间
set global long_query_time=1;
查找慢查询
将慢查询记录到日志中查看慢查询记录日志是否开启
show variables like ‘slow%’;
开启慢查询记录
set global slow_query_log=ON;
日志文件地址

使用
Druid的
sql分析
配置
Druid连接池
访问
/druid/index.html地址

EXPLAIN 命令
MySQL的
EXPLAIN命令用于
SQL语句的查询执行计划
(QEP)。这条命令的输出结果能够让我们了解
MySQL优化器是如何执行
SQL语句的。这条命令并没有提供任何调整建议,但它能够提供重要的信息帮助你做出调优决策。
语法
MySQL的
EXPLAIN语法可以运行在
SELECT语句或者特定表上(5.6之后允许
EXPLAIN非
SELECT查询)。
UPDATE city SET name='chengdu' WHERE id=1
==>
SELECT name FROM city WHERE id=1
命令详解

QEP中的列表参数:
id
查询语句的标识符,如果有零时表则为NULL。
select_type
查询类型。包含的类型有:
SIMPLE:简单的查询(没有使用
UNION或子查询)
PRIMARY:查询中最外层的
SELECT(如两表做
UNION或者存在子查询的外层的表操作为
PRIMARY,内层的操作为
UNION)
UNION:
UNION操作中,查询中处于内层的
SELECT(内层的
SELECT语句与外层的
SELECT语句没有依赖关系)
DEPENDENT UNION:
UNION操作中,查询中处于内层的
SELECT(内层的
SELECT语句与外层的
SELECT语句有依赖关系)
UNION RESULT:
UNION操作的结果,
id值通常为
NULL
SUBQUERY:子查询中首个
SELECT(如果有多个子查询存在)
DEPENDENT SUBQUERY:子查询中首个
SELECT,但依赖于外层的表(如果有多个子查询存在)
DERIVED:被驱动的
SELECT子查询(子查询位于
FROM子句)
UNCACHEABLE SUBQUERY:对于外层的主表,子查询不可被物化,每次都需要计算(耗时操作)
UNCACHEABLE UNION:
UNION操作中,内层的不可被物化的子查询(类似于
UNCACHEABLE SUBQUERY)
table
输出行所用到的表的名称。也可能是以下形式:
<unionM,N>: 该行是具有
M和
N的
id值的行的联合行
<derivedN>: 该行引用
id值为
N的行的派生表结果
partitions
记录将与查询匹配的分区,这一列只有在
EXPLAIN PARTITIONS语法中才会出现
type
代表QEP 中指定的表使用的连接方式。下面是最常用的几种连接方式:
const: MySql对查询的部分进行优化并将其转换为一个常亮时,
system这是
const的特例,当表只有一个
row时会出现
SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
eq_ref: 索引查找,MySql知道最多返回一条符合条件的记录。
eq_ref可用于使用
=运算符进行比较的索引列.
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
ref:索引查找,返回所有匹配某个单个值的行,
ref可以用于使用
=或
<=>运算符进行比较的索引列
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
range:有限制的索引扫描,
range可以用于使用任何
=,<>,>,> =,<,<=,IS NULL,& 4000 lt;=>,BETWEEN或IN()运算符将键列与常量进行比较
SELECT * FROM tbl_name WHERE key_column = 10; SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name WHERE key_column IN (10,20,30); SELECT * FROM tbl_name WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
ALL:这个值表示需要一次全表扫描,其他类型的值还有
fulltext 、ref_or_null 、index_merge 、unique_subquery、index_subquery 以及index。
index:和全表扫描一样,只是MySql扫描表时按索引次序进行而不是行。优点是避免了排序;缺点是要承担索引次序读取整个表的开销。
possible_keys
可以从中选择查找表中的行的索引,如果这个列是
NULL,那么没有相关的索引
key
MySQL实际决定使用的关键字(索引)。如果
MySQL决定使用其中一个
possible_keys索引来查找行,则该索引被列为关键值。如果所有的
possible_keys都不合适,也可能选取其他的
key
key_len
MySQL实际使用的关键字(索引)长度
ref
ref列可以被用来标识那些用来进行索引比较的列或者常量。
rows
rows表示
MySQL认为它必须检查以执行查询的行数。
filtered(这一列只有在EXPLAINED EXTENDED 语法中才会出现)
filtered表示将由表条件过滤的表行的估计百分比。
Extra
有关MySQL如何解析查询的其他信息
Using where
表示
Mysql将在
storage engine检索行后再进行过滤。
Using index
仅使用索引树中的信息从表中检索列信息,而不需要进行附加搜索来读取实际行(使用二级覆盖索引即可获取数据)。 当查询仅使用作为单个索引的一部分的列时,可以使用此策略。

Using index condition
Using index condition会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用
WHERE子句中的其他条件去过滤这些数据行。

因为
MySQL的架构原因,分成了
server层和
引擎层,才有所谓的
“下推(push down)”的说法。所以ICP其实就是实现了
index filter技术,将原来的在
server层进行的table filter中可以进行index filter的部分,在引擎层面使用index filter进行处理,不再需要回表进行table filter

Using filesort
当
Query中包含
ORDER BY操作,而且无法利用索引完成排序操作的时候,
MySQL Query Optimizer不得不选择相应的排序算法来实现。数据较少时从内存排序,否则从磁盘排序。
Using temporary
要解决查询,
MySQL需要创建一个临时表来保存结果。 如果查询包含不同列的
GROUP BY和
ORDER BY子句,则通常会发生这种情况。
Using join buffer (Block Nested Loop), Using join buffer (Batched Key Access)
Block Nested-Loop Join算法:将外层循环的行/结果集存入
join buffer, 内层循环的每一行与整个
buffer中的记录做比较,从而减少内层循环的次数。
Batched Key Access算法:对于多表
join语句,当
MySQL使用索引访问第二个
join表的时候,使用一个
join buffer来收集第一个操作对象生成的相关列值。BKA构建好
key后,批量传给引擎层做索引查找。
使用 EXPLAIN 命令进行分析
查询子句
where条件查询
比较运算符
主键判等,
const等级

主键比较,
range等级

索引查询,
ref等级

IN查询,会全表扫描

逻辑运算符
and ( && )逻辑与

not ( ! )逻辑非

or ( || )逻辑或,会全表扫描

模糊查询
like右模糊会全表扫描,左模糊无法使用索引


group by分组

having筛选
order by排序
主键排序,主键自带排序

索引排序,非主键的排序需要:
Using filesort,
phone索引无法完成排序操作

一般排序,非主键的排序需要:
Using filesort

limit条数限制
子查询
where型子查询(把内层查询结果当作外层查询的比较条件)

from型子查询(把内层的查询结果供外层再次查询)

exists型子查询(把外层查询结果拿到内层,看内层的查询是否成立)

UNION
UNION查询

因为需要移除相同数据,所以需要额外的零时表(
Using temporary)
UNION ALL查询

左连接,右连接,内连接
LEFT JOIN

RIGHT JOIN
a left join b 等价于 b right join a
推荐使用左连接代替右连接
INNER JOIN

相关文章推荐
- 【MySQL性能优化】Mysql基本性能分析命令详解-EXPLAIN
- MySQL性能分析命令:Explain 详解
- MySQL Study之--MySQL优化分析工具explain
- mysql 性能分析之explain详解
- mysql之explain详解(分析索引的最佳使用)
- 详解Mysql多表联合查询效率分析及优化
- 性能优化之MySQL优化(二)- explain分析SQL
- MySQL 性能优化——「Explain 分析实践」
- 详解Mysql多表联合查询效率分析及优化
- mysql性能优化-慢查询分析、优化索引和配置 (慢查询日志,explain,profile)
- MySQL技巧#MySQL性能分析之explain的详解
- MySQL 性能优化神器 Explain 使用分析
- mysql之explain使用详解(分析索引)
- mysql优化(三)–explain分析sql语句执行效率
- 【MySQL性能优化】Mysql基本性能分析命令详解(3)
- mysql优化----explain的列分析
- 【MySql性能优化二】利用explain进行查询和分析sql语句
- 【Explain】mysql之explain详解(分析索引的最佳使用)
- MySQL优化 之 用explain分析低效率的sql语句
- 【MySQL性能优化】Mysql基本性能分析命令详解