深入探索SQL优化:利用慢查询日志和explain提升数据库效率

优化概述

数据库性能取决于数据库级别的多个因素,例如表、查询和配置设置。这些软件构造会导致硬件级别的 CPU 和 I/O 操作,您必须将其最小化并尽可能高效。

典型用户的目标是从其现有软件和硬件配置中获得最佳数据库性能。高级用户寻找机会改进MySQL软件本身,或开发自己的存储引擎和硬件设备来扩展MySQL生态系统。
(1)在数据库级别进行优。
(2)在硬件级别进行优化。
(3)平衡便携性和性能。

优化器成本

MySQL 优化器主要针对 IO 和 CPU 会计算语句的成本;可能不会按照分析的原理来执行语句。

成本分析步骤:
(1)找出所有可能需要使用到的索引。
(2)计算全表扫描的代价。
(3)计算不同索引执行查询的代价。
(4)对比找出代价最小的执行方案。

EXPLAIN

用来查看 SQL 语句的具体执行过程。
原理:模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理 SQL 语句的。

执行计划

ColumnMeaning
idThe SELECT identifier (查询id)
select_typeThe SELECT type (查询类型)
tableThe table for the output row (输出结果集的表)
partitionsThe matching partitions (匹配的分区)
typeThe join type (表的连接类型)
possible_keysThe possible indexes to choose(可能使用的索引)
keyThe index actually chosen (实际使用的索引)
key_lenThe length of the chosen key (索引字段的长度)
refThe columns compared to the index (列与索引的比较)
rowsEstimate of rows to be examined (预估扫描行数)
filteredPercentage of rows filtered by tablecondition (按表条件过滤的行百分比)
extraAdditional information (额外信息,如是否使用索引覆盖)

示例:

DROP TABLE IF EXISTS `covering_index_t`;
CREATE TABLE `covering_index_t` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(255) DEFAULT NULL,
	`cid` INT(11) DEFAULT NULL,
	`age` SMALLINT DEFAULT 0,
	`score` SMALLINT DEFAULT 0,
	PRIMARY KEY (`id`),
	KEY `name_cid_idx` (`name`, `cid`)
)ENGINE = INNODB AUTO_INCREMENT=0 DEFAULT CHARSET = utf8;


INSERT INTO `covering_index_t` (`name`, `cid`, `age`, `score`)
VALUES
	('FLY', 10001, 12, 99),
	('fly', 10002, 13, 98),
	('cc', 10003, 14, 97),
	('qq', 10004, 15, 100);

EXPLAIN SELECT * FROM `covering_index_t` WHERE `name` = 'mark';

id

select 查询的序列号,包含一组数字,表示查询中执行select 子句或者操作表的顺序。
id 号分为三种情况:

  1. id 相同,那么执行顺序从上到下。
  2. id 不同,id 越大越先执行。
  3. id 有相同的也有不同的,id 相同的按 1 执行,id 不同的按 2 执行。

select_type

主要用来分辨查询的类型,是普通查询还是联合查询还是子查询。

select_type valueMeaning
SIMPLE简单查询-没有联合查询和子查询
PRIMARY最外层select
UNION若第二个select出现在union之后,则被标记为union
DEPENDENT UNIONunion或union all联合而成的结果会受外部表影响
UNION RESULT从union表获取结果的select
SUBQUERYselect或者where列表中包含子查询
DEPENDENT SUBQUERYsubquery的子查询要受到外部表查询的影响
DERIVEDfrom子句中出现的子查询,也叫做派生表
UNCACHEABLE SUBQUERY一个子查询,其结果不能被缓存,必须为外部查询的每一行重新求值。表示使用子查询的结果不能被缓存。
UNCACHEABLE UNION表示union的查询结果不能被缓存:sql语句未验证

table

对应行正在访问哪一个表,表名或者别名,可能是临时表或者union 合并结果集。

  1. 具体表名或者表的别名,从具体的物理表中获取数据。
  2. 表明为 derivedN 的形式,表示 id 为 N 的查询产生的衍生表。
  3. 当有 union result 的时候,表名是 union n1,n2 等的形式,n1,n2 表示参与 union的 id。

type

type 显示访问类型;采用怎么样的方式来访问数据;效率从好到坏依次为:

system > const > eq_ref > ref > fulltext > ref_or_null >index_merge > unique_subquery > index_subquery > range> index > ALL

type valuemeaning
ALL全表扫描;如果数据量大则需要进行优化
index全索引扫描这个比 ALL 的效率要好,主要有两种情况,一种是当前的查询是覆盖索引,即需要的数据在索引中就可以索取,或者是使用了索引进行排序,这样就避免数据的重排序。
range表示利用索引查询的时候限制了范围,在指定范围内进行查询,这样避免了 index 的全索引扫描,适用的操作符:= , <> , > , >= , < , <= , IS NULL , BETWEEN , LIKE , or IN()
index_subquery利用索引来关联子查询,不再扫描全表
unique_subquery该连接类型类似与 index_subquery,使用的是唯一索引
index_merge在查询过程中需要多个索引组合使用
ref_or_null对于某个字段即需要关联条件,也需要 null值的情况下,查询优化器会选择这种访问方式
ref使用了非唯一性索引进行数据的查找
eq_ref使用唯一性索引进行数据查找
const这个表至多有一个匹配行
system表只有一行记录(等于系统表),这是 const 类型的特例

possible_keys

查询涉及到字段的索引,则这些索引都会列举出来,但是不一定采纳。

key

实际使用的索引,如果为 NULL,则没有使用索引。

key_len

表示索引中使用的字节数;查询中使用的索引长度;在不损失精度的情况下长度越短越好。

ref

显示索引的哪一列被使用了,如果可能的话,是一个常数。

rows

大致估算出找出所需记录需要读取的行数,反映了sql找了多少条数据,该值越小越好。

extra

额外信息。

extra valuemeaning
using filesort使用了文件排序
using temporary建立临时表来保存中间结果,查询完成之后把临时表删除
using index采用覆盖索引,直接从索引中读取数据,而不用访问数据表。如果同时出现 using where 表明索引被用来执行索引键值的查找;如果没有,表明索引被用来读取数据,而不是真的查找
using index condition采用索引下推,减少回表次数
using where使用 where 进行条件过滤
using join buffer使用连接缓存
impossible wherewhere 语句的结果总是 false

优化器选择过程

优化器根据解析树可能会生成多个执行计划,然后选择最优的的执行计划。

SHOW VARIABLES LIKE 'optimizer_trace';
-- 启用优化器的追踪
SET optimizer_trace='enabled=on';
-- 执行一条查询语句
SELECT * FROM information_schema.optimizer_trace;
-- 用完关闭
SET optimizer_trace="enabled=off";
SHOW VARIABLES LIKE 'optimizer_trace';

慢日志查询

慢查询日志由执行时间超过 long_query_time 秒且至少需要检查 min_examined_row_limit 行的 SQL 语句组成。慢查询日志可用于查找需要很长时间才能执行的查询,因此是优化的候选项。但是,检查较长的慢查询日志可能是一项耗时的任务。为了简化此操作,您可以使用 mysqldumpslow 命令来处理慢查询日志文件并汇总其内容。

慢查询日志参数

long_query_time的最小值和默认值分别为 0 和 10。可以将该值指定为微秒的分辨率。

缺省情况下,不记录管理语句,也不记录不使用索引进行查找的查询。可以使用log_slow_admin_statements和log_queries_not_using_indexes更改此行为,默认情况下,慢查询日志处于禁用状态。

开启

(1)查看:

SHOW GLOBAL VARIABLES LIKE 'slow_query%';
SHOW GLOBAL VARIABLES LIKE 'long_query%';

(1)设置:

SET GLOBAL slow_query_log = ON;  -- on 开启 off,关闭
SET GLOBAL long_query_time = 4;   -- 单位秒;默认 10s;此时设置为4s

或者修改配置:

slow_query_log = ON
long_query_time = 4
slow_query_log_file = D:/mysql/mysql57-slow.log

mysqldumpslow

查找最近10条慢查询日志:

mysqldumpslow -s t -t 10 -g 'select' D:/mysql/mysql57-slow.log

总结

当出现SQL比较慢时,需要进行如下步骤进行优化:
(1)找到SQL语句。通过show processlist和开启慢查询日志。
(2)分析SQL语句。
a. 查看where、group by、order by里面的字段是否创建了索引。
b. in 优化成联合查询,减少联合查询等。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值