【1】分析优化器执行计划:trace
OPTIMIZER_TRACE
是MySQL5.6引入的一项跟踪功能,它可以跟踪优化器做出的各种决策(比如访问表的方法、各种开销计算、各种转换等),并将跟踪结果记录到INFORMATION_SCHEMA.OPTIMIZER_TRACE
表中。
此功能默认关闭,需要手动开启。开启trace,并设置格式为json,同时设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示。
set optimizer_trace='enabled=on',end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;
使用命令查看开启后的状态:
show VARIABLES like '%optimizer_trace%'
开启后,可以分析如下语句:select、insert、replace、update、delete、explain、set、declare、case、if、return、call。
测试如下:
select * from s1 where id < 10005;
explain select * from s1 where id < 10005;
其explain执行结果如下:
SELECT* from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
我们会得到如下结果:
- Query:我们执行的查询语句。
- MISSING_BYTES_BEYOND_MAX_MEM_SIZ : 跟踪信息过长时,被截断的跟踪信息的字节数。
- INSUFFICIENT_PRIVILEGES:执行跟踪语句的用户是否有查看对象的权限,当不具有权限时,该列信息为1且trace字段为空。一般在调用带有SQL SECURITY DEFINER的视图或者是存储过程的情况下,会出现此问题。
- TRACE:也是核心部分,QUERY字段对应语句的跟踪信息。
我们将TRACE拷贝出来,如下所示。
{
"steps": [
{
"join_preparation": { # 准备工作
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `s1`.`id` AS `id`,`s1`.`key1` AS `key1`,`s1`.`key2` AS `key2`,`s1`.`key3` AS `key3`,`s1`.`key_part1` AS `key_part1`,`s1`.`key_part2` AS `key_part2`,`s1`.`key_part3` AS `key_part3`,`s1`.`common_field` AS `common_field` from `s1` where (`s1`.`id` < 10005)"
}
]/*steps*/
}/*join_preparation*/
},
{
"join_optimization": { # 进行优化
"select#": 1,
"steps": [
{
"condition_processing": { # 条件处理
"condition": "WHERE",
"original_condition": "(`s1`.`id` < 10005)",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`s1`.`id` < 10005)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(`s1`.`id` < 10005)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`s1`.`id` < 10005)"
}
]/*steps*/
}/*condition_processing*/
},
{
"substitute_generated_columns": {# 替换生成的列
}/*substitute_generated_columns*/
},
{
"table_dependencies": [# 表的依赖关系
{
"table": "`s1`",
"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": "`s1`",
"range_analysis": {
"table_scan": {
"rows": 9895,
"cost": 1015.85
}/*table_scan*/, # 扫描表
# 潜在的范围索引
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": [
"id"
]/*key_parts*/
},
{
"index": "idx_key2",
"usable": true,
"key_parts": [
"key2"
]/*key_parts*/
},
{
"index": "idx_key1",
"usable": true,
"key_parts": [
"key1",
"id"
]/*key_parts*/
},
{
"index": "idx_key3",
"usable": true,
"key_parts": [
"key3",
"id"
]/*key_parts*/
},
{
"index": "idx_key_part",
"usable": true,
"key_parts": [
"key_part1",
"key_part2",
"key_part3",
"id"
]/*key_parts*/
}
]/*potential_range_indexes*/,
# 设置范围条件
"setup_range_conditions": [
]/*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"
},
{
"index": "idx_key2",
"usable": false,
"cause": "query_references_nonkey_column"
},
{
"index": "idx_key1",
"usable": false,
"cause": "query_references_nonkey_column"
},
{
"index": "idx_key3",
"usable": false,
"cause": "query_references_nonkey_column"
},
{
"index": "idx_key_part",
"usable": false,
"cause": "query_references_nonkey_column"
}
]/*potential_skip_scan_indexes*/
}/*skip_scan_range*/,
# 分析范围选项
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "PRIMARY",
"ranges": [
"id < 10005"
]/*ranges*/,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 3,
"cost": 0.561603,
"chosen": true
},
{
"index": "idx_key1",
"chosen": false,
"cause": "no_valid_range_for_this_index"
},
{
"index": "idx_key3",
"chosen": false,
"cause": "no_valid_range_for_this_index"
},
{
"index": "idx_key_part",
"chosen": false,
"cause": "no_valid_range_for_this_index"
}
]/*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": 3,
"ranges": [
"id < 10005"
]/*ranges*/
}/*range_access_plan*/,
"rows_for_plan": 3,
"cost_for_plan": 0.561603,
"chosen": true
}/*chosen_range_access_summary*/
}/*range_analysis*/
}
]/*rows_estimation*/
},
{
# 考虑执行计划
"considered_execution_plans": [
{
"plan_prefix": [
]/*plan_prefix*/,
"table": "`s1`",
"best_access_path": { # 最棒访问路径
"considered_access_paths": [
{
"rows_to_scan": 3,
"access_type": "range",
"range_details": {
"used_index": "PRIMARY"
}/*range_details*/,
"resulting_rows": 3,
"cost": 0.861603,
"chosen": true
}
]/*considered_access_paths*/
}/*best_access_path*/,
# 行过滤百分比
"condition_filtering_pct": 100,
"rows_for_plan": 3,
"cost_for_plan": 0.861603,
"chosen": true
}
]/*considered_execution_plans*/
},
{
# 将条件附加到表上
"attaching_conditions_to_tables": {
"original_condition": "(`s1`.`id` < 10005)",
"attached_conditions_computation": [
]/*attached_conditions_computation*/,
"attached_conditions_summary": [
# 附加条件摘要
{
"table": "`s1`",
"attached": "(`s1`.`id` < 10005)"
}
]/*attached_conditions_summary*/
}/*attaching_conditions_to_tables*/
},
{
"finalizing_table_conditions": [
{
"table": "`s1`",
"original_table_condition": "(`s1`.`id` < 10005)",
"final_table_condition ": "(`s1`.`id` < 10005)"
}
]/*finalizing_table_conditions*/
},
{
"refine_plan": [# 精简计划
{
"table": "`s1`"
}
]/*refine_plan*/
}
]/*steps*/
}/*join_optimization*/
},
{
"join_execution": {# 执行
"select#": 1,
"steps": [
]/*steps*/
}/*join_execution*/
}
]/*steps*/
}
【2】MySQL监控分析视图
关于MySQL的性能监控和问题诊断,我们一般都从performance_schema中去获取想要的数据。在MySQL5.7.7版本中新增sys schema,它将performance_schema 和 information_schema中的数据以更容易理解的方式总结归纳为“视图”,其目的就是为了降低查询performance_schema的复杂度,让DBA能够快速的定位问题。
① 基本介绍
主机相关 : 以host_summary开头,主要汇总了IO延迟的信息。
InnoDB相关:以innodb开头,汇总了innodb buffer信息和事务等待innodb锁的信息。
IO相关:以IO开头,汇总了等待IO、IO使用量情况。
内存使用情况 :以memory开头,从主机、线程、事件等角度展示内存的使用情况。
连接与会话信息:processlist和session相关视图,总结了会话相关信息。
表相关:以schema_table开头的视图,展示表的统计信息。
索引信息:统计了索引的使用情况,包含冗余索引和未使用的索引情况。
语句相关:以statement开头,包含执行全表扫描、使用临时表、排序等的语句信息。
用户相关:以user开头的视图,统计了用户使用的文件IO、执行语句统计信息。
等待事件相关信息:以wait开头,展示等待事件的延迟情况。
在sys数据库的视图里面我们可以看到这些具体视图信息。
② Sys schema视图使用场景
① 索引情况
查询冗余索引
select * from sys.schema_redundant_indexes
查询未使用过的索引
select * from sys.schema_unused_indexes
查询索引的使用情况
select index_name,rows_selected,rows_inserted,rows_updated,rows_deleted
from sys.schema_index_statistics where table_schema='dbname';
② 表相关
查询表的访问量
select table_schema,table_name,sum(io_read_requests+io_write_requests) as io
from sys.schema_table_statistics group by table_schema,table_name
order by io desc;
查询占用bufferpool较多的表
select object_schema,object_name,allocated,data
from sys.innodb_buffer_stats_by_table
order by allocated limit 10;
查询表的全表扫描情况
select * from sys.statements_with_full_table_scans
where db='dbname';
③ 语句相关
监控SQL执行的频率
select db,exec_count,query from sys.statement_analysis
order by exec_count desc;
监控使用了排序的SQL
select db,exec_count,first_seen,last_seen,query
from sys.statements_with_sorting limit 10;
监控使用了临时表或者磁盘临时表的SQL
select db,exec_count,tmp_tables,tmp_disk_tables,query
from sys.statement_analysis
where tmp_tables >0 or tmp_disk_tables > 0
order by (tmp_tables+tmp_disk_tables) desc;
④ IO相关
查看消耗磁盘IO的文件
select file,avg_read,avg_write,avg_read+avg_write as avg_io
from sys.io_global_by_file_by_bytes
order by avg_read
limit 10;
⑤ InnoDB相关
行所阻塞情况
select * from sys.innodb_lock_waits;
通过sys库去查询时,MySQL会消耗大量资源去收集相关信息,严重的可能会导致业务请求被阻塞,从而引起故障。建议生产上不要频繁的去查询sys或者performance_schema information_schame来完成监控、巡检等工作。