此笔记为尚硅谷MySQL高级篇部分内容
目录
一、数据库服务器的优化步骤
当我们遇到数据库调优问题的时候,该如何思考呢?这里把思考的流程整理成下面这张图。
整个流程划分成了 观察(Show status) 和 行动(Action) 两个部分。字母 S 的部分代表观察(会使用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。
小结:
二、查看系统性能参数
在MySQL中,可以使用 SHOW STATUS 语句查询一些MySQL数据库服务器的 性能参数 、 执行频率 。
SHOW STATUS语句语法如下:
SHOW [GLOBAL|SESSION] STATUS LIKE '参数';
三、统计SQL的查询成本:last_query_cost
使用场景:它对于比较开销是非常有用的,特别是我们有好几种查询方式可选的时候。
四、定位执行慢的 SQL:慢查询日志
1、开启慢查询日志参数
1.开启slow_query_log
mysql > set global slow_query_log='ON';
2. 修改long_query_time阈值
接下来我们来看下慢查询的时间阈值设置,使用如下命令:
mysql > show variables like '%long_query_time%';
这里如果我们想把时间缩短,比如设置为 1 秒,可以这样设置:
#测试发现:设置global的方式对当前session的long_query_time失效。对新连接的客户端有效。所以可以一并
执行下述语句
mysql > set global long_query_time = 1;
mysql> show global variables like '%long_query_time%';
mysql> set long_query_time=1;
mysql> show variables like '%long_query_time%';
2、查看慢查询数目
查询当前系统中有多少条慢查询记录
SHOW GLOBAL STATUS LIKE '%Slow_queries%';
3、慢查询日志分析工具:mysqldumpslow
在生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具mysqldumpslow 。
查看mysqldumpslow的帮助信息
mysqldumpslow --help
工作常用参考:
#得到返回记录集最多的10个SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log
#得到访问次数最多的10个SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/atguigu-slow.log
#得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/atguigu-slow.log
#另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log | more
4、关闭慢查询日志
除了调优需要开,正常还是不要开了
MySQL服务器停止慢查询日志功能有两种方法:
5、删除慢查询日志
五、查看 SQL 执行成本:SHOW PROFILE
Show Profile是MySQL提供的可以用来分析当前会话中SQL都做了什么、执行的资源消耗情况的工具,可用于sql调优的测量。默认情况下处于关闭状态
,并保存最近15次的运行结果。
show variables like 'profiling';
--通过设置 profiling='ON’ 来开启 show profile:
mysql > set profiling = 'ON';
--然后执行相关的查询语句。接着看下当前会话都有哪些 profiles,使用下面这条命令:
mysql > show profiles;
--你能看到当前会话一共有 2 个查询。如果我们想要查看最近一次查询的开销,可以使用:
mysql > show profile;
--我们也可以查看指定的Query lD的开销,比如`show profile for query 2`查询结果是一样的。在SHOWPROFILE中我们可以查看不同部分的开销,比如cpu、block.io等:
mysql> show profile cpu,block io for query 2;
六、分析查询语句:EXPLAIN
1、概述
官网介绍
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
能做什么?
-
表的读取顺序
-
数据读取操作的操作类型。
-
哪些索引可以使用
-
哪些索引被实际使用
-
表之间的引用
-
每张表有多少行被优化器查询
2、基本语法
EXPLAIN 或 DESCRIBE语句的语法形式如下:
EXPLAIN SELECT select_options
--或者
DESCRIBE SELECT select_options
EXPLAIN 语句输出的各个列的作用如下:
列名 | 描述 |
---|---|
id | 在一个大的查询语句中每个SELECT关键字都对应一个 唯一的id |
select_type | SELECT关键字对应的那个查询的类型 |
table | 表名 |
partitions | 匹配的分区信息 |
type | 针对单表的访问方法(重要) |
possible_keys | 可能用到的索引 |
key | 实际上使用的索引 |
key_len | 实际使用到的索引长度 |
ref | 当使用索引列等值查询时,与索引列进行等值匹配的对象信息 |
rows | 预估的需要读取的记录条数 |
filtered | 某个表经过搜索条件过滤后剩余记录条数的百分比 |
Extra | 一些额外的信息 |
3、EXPLAIN各列作用
具体使用例子可以查看上传的代码包
1. table
2. id
正常来说一个select 一个id ,也有例外的可能,查询优化器做了优化
mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
查询优化器优化
######查询优化器可能对涉及子查询的查询语句进行重写,转变为多表查询的操作########
EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key2 FROM s2 WHERE common_field = 'a');
Union去重
原本想的1个select 一个 id , 预计两个。
--Union去重
EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
--union all 不去重 所以不需要放在临时表里面
EXPLAIN SELECT * FROM s1 UNION ALL SELECT * FROM s2;
3.select_type
名称 | 描述 |
---|---|
SIMPLE | Simple SELECT (not using UNION or subqueries) |
PRIMARY | Outermost SELECT |
UNION | Second or later SELECT statement in a UNION |
UNION RESULT | Result of a UNION |
SUBQUERY | First SELECT in subquery |
DEPENDENT SUBQUERY | First SELECT in subquery, dependent on outer query |
DEPENDENT UNION | Second or later SELECT statement in a UNION, dependent on outer query |
DERIVED | Derived table |
MATERIALIZED | Materialized subquery |
UNCACHEABLE SUBQUERY | A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query |
UNCACHEABLE UNION | The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY) |
4.partitions (可略)
代表分区表中的命中情况,非分区表,该项为NULL。一般情况下我们的查询语句的执行计划的partitions列的值都是NULL。
5. type ☆
--`system` 当表中`只有一条记录`并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是`system`。
--const #当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是`const`
--eq_ref #在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则对该被驱动表的访问方法就是`eq_ref`
--ref #当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是`ref`
--fulltext 全文索引
--ref_or_null #当对普通二级索引进行等值匹配查询,该索引列的值也可以是`NULL`值时,那么对该表的访问方法就可能是`ref_or_null`
--index_merge #单表访问方法时在某些场景下可以使用`Intersection`、`Union`、`Sort-Union`这三种索引合并的方式来执行查询
--unique_subquery #`unique_subquery`是针对在一些包含`IN`子查询的查询语句中,如果查询优化器决定将`IN`子查询,转换为`EXISTS`子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的`type`,列的值就是`unique_subquery`
--`index_subquery`
--range #如果使用索引获取某些`范围区间`的记录,那么就可能使用到`range`访问方法
--index #当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是`index`
--ALL #一般来说,这些访问方法中除了`All`这个访问方法外,其余的访问方法都能用到索引,除了`index_merge`访问方法外,其余的访问方法都最多只能用到一个索引。
小结:
结果值从最好到最坏依次是:
system > const > eq_ref > ref >
fulltext > ref_or_null > index_merge >unique_subquery > index_subquery > range >
index > ALL
SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,最好是 consts级别。(阿里巴巴 开发手册要求)
6.possible_keys和key
7.key_len ☆
8.ref
当使用索引列等值查询时,与索引列进行等值匹配的对象信息。比如只是一个常数或者是某个列
9.rows ☆
rows:预估的需要读取的记录条数,`值越小越好`,通常与filtered 一起使用
rows 值越小,代表,数据越有可能在一个页里面,这样io就会更小。
10.filtered
11.Extra ☆
12.小结
- EXPLAIN不考虑各种Cache
- EXPLAIN不能显示MySQL在执行查询时所作的优化工作
- EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
- 部分统计信息是估算的,并非精确值
七、EXPLAIN的进一步使用
1、EXPLAIN四种输出格式
这里谈谈EXPLAIN的输出格式。EXPLAIN可以输出四种格式: 传统格式 , JSON格式 , TREE格式 以及 可视化输出 。用户可以根据需要选择适用于自己的格式。
1. 传统格式
2. JSON格式
3.TREE格式
TREE格式是8.0.16版本之后引入的新格式,主要根据查询的 各个部分之间的关系 和 各部分的执行顺序 来描述如何查询
4.可视化输出
可视化输出,可以通过MySQL Workbench可视化查看MySQL的执行计划。通过点击Workbench的放大镜图标,即可生成可视化的查询计划。
上图按从左到右的连接顺序显示表。红色框表示 全表扫描 ,而绿色框表示使用 索引查找 。对于每个表,显示使用的索引。还要注意的是,每个表格的框上方是每个表访问所发现的行数的估计值以及访问该表的成本。
2、SHOW WARNINGS的使用
八、分析优化器执行计划:trace
mysql> select * from information_schema.optimizer_trace\G
*************************** 1. row ***************************
# //第1部分:查询语句
QUERY: select * from student where id < 10
//第2部分:QUERY字段对应语句的跟踪信息
TRACE: {
"steps": [
{
"join_preparation": { /*预备工作*/
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `student`.`id` AS `id`,`student`.`stuno` AS `stuno`,`student`.`name` AS `name`,`student`.`age` AS `age`,`student`.`classId` AS `classId` from `student` where (`student`.`id` < 10)"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {/*进行优化*/
"select#": 1,
"steps": [
{
"condition_processing": {/*条件处理*/
"condition": "WHERE",
"original_condition": "(`student`.`id` < 10)",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`student`.`id` < 10)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(`student`.`id` < 10)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`student`.`id` < 10)"
}
] /* steps */
} /* condition_processing */
},
{
"substitute_generated_columns": {/*替换生成的列*/
} /* substitute_generated_columns */
},
{
"table_dependencies": [ /* 表的依赖关系*/
{
"table": "`student`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"ref_optimizer_key_uses": [ /* 使用键*/
] /* ref_optimizer_key_uses */
},
{
"rows_estimation": [ /*行判断*/
{
"table": "`student`",
"range_analysis": {
"table_scan": {
"rows": 3945207,
"cost": 404306
} /* table_scan */,/*表扫描*/
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": [
"id"
] /* key_parts */
}
] /* potential_range_indexes */,
"setup_range_conditions": [
] /* 设置条件范围 */,
"group_index_range": {
"chosen": false,
"cause": "not_group_by_or_distinct"
} /* group_index_range */,
"skip_scan_range": {
"potential_skip_scan_indexes": [
{
"index": "PRIMARY",
"usable": false,
"cause": "query_references_nonkey_column"
}
] /* potential_skip_scan_indexes */
} /* skip_scan_range */,
"analyzing_range_alternatives": {/*分析范围选项*/
"range_scan_alternatives": [
{
"index": "PRIMARY",
"ranges": [
"id < 10"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"in_memory": 0.159895,
"rows": 9,
"cost": 1.79883,
"chosen": true
}
] /* range_scan_alternatives */,
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */,
"chosen_range_access_summary": {/*选择范围访问摘要*/
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 9,
"ranges": [
"id < 10"
] /* ranges */
} /* range_access_plan */,
"rows_for_plan": 9,
"cost_for_plan": 1.79883,
"chosen": true
} /* chosen_range_access_summary */
} /* range_analysis */
}
] /* rows_estimation */
},
{
"considered_execution_plans": [/*考虑执行计划*/
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`student`",
"best_access_path": {/*最佳访问路径*/
"considered_access_paths": [
{
"rows_to_scan": 9,
"access_type": "range",
"range_details": {
"used_index": "PRIMARY"
} /* range_details */,
"resulting_rows": 9,
"cost": 2.69883,
"chosen": true
}
] /* considered_access_paths */
} /* best_access_path */,
"condition_filtering_pct": 100, /*行过滤百分比*/
"rows_for_plan": 9,
"cost_for_plan": 2.69883,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": { /*将条件附加到表上*/
"original_condition": "(`student`.`id` < 10)",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [ /*附加条件概要*/
{
"table": "`student`",
"attached": "(`student`.`id` < 10)"
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"finalizing_table_conditions": [
{
"table": "`student`",
"original_table_condition": "(`student`.`id` < 10)",
"final_table_condition ": "(`student`.`id` < 10)"
}
] /* finalizing_table_conditions */
},
{
"refine_plan": [ /*精简计划*/
{
"table": "`student`"
}
] /* refine_plan */
}
] /* steps */
} /* join_optimization */
},
{
"join_execution": { /*执行*/
"select#": 1,
"steps": [
] /* steps */
} /* join_execution */
}
] /* steps */
}
/
/*第3部分:跟踪信息过长时,被截断的跟踪信息的字节数。*/
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0 /*丢失的超出最大容量的字节*/
/*第4部分:执行跟踪语句的用户是否有查看对象的权限。当不具有权限时,该列信息为1且TRACE字段为空,一般在
调用带有SQL SECURITY DEFINER的视图或者是存储过程的情况下,会出现此问题。*/
INSUFFICIENT_PRIVILEGES: 0 /*缺失权限*/
1 row in set (0.01 sec)
九、MySQL监控分析视图-sys schema
1、Sys schema视图摘要
2、Sys schema视图使用场景
高级篇笔记PDF自取
链接:https://pan.baidu.com/s/1pVqrTwIZFoED77i-EFmw6g?pwd=3333
提取码:3333