Trace分析优化器执行计划与Sys schema视图的使用详解

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Trace分析优化器执行计划与Sys schema视图的使用详解

【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%'

d8c7938d05bc41fca67d3eee7431841d.png

开启后,可以分析如下语句: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数据库的视图里面我们可以看到这些具体视图信息。


2a4d9da8fc244e8b8424c658d59139dc.png

② 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来完成监控、巡检等工作。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
SQL NoSQL MySQL
MongoDB 执行计划 & 优化器简介 (上)
最近,由于工作需求去了解一下Query是如何在MongoDB内部进行处理,从而丢给存储引擎的。里面涉及了Query执行计划和优化器的相关代码,MongoDB整体思路设计的干净利落,有些地方深入挖一下其实还是能有些优化点的。本文会涉及一条Query被parse之后一路走到引擎之前,都做了那些事情,分析基于MongoDB v3.4.6代码。由于篇幅过长,文章分为上下两篇,分别介绍执行计划 & 优化器和
3775 0
|
SQL JSON 关系型数据库
几个必须掌握的SQL优化技巧(四):使用Trace工具分析优化器执行计划
在应用的开发过程中,由于开发初期的数据量一般都比较小,所以开发过程中一般都比较注重功能上的实现,但是当完成了一个应用或者系统之后,随着生产数据量的急剧增长,那么之前的很多sql语句的写法就会显现出一定的性能问题,对生产的影响也会越来越大,这些不恰当的sql语句就会成为整个系统性能的瓶颈,为了追求系统的极致性能,必须要对它们进行优化。
425 0
几个必须掌握的SQL优化技巧(四):使用Trace工具分析优化器执行计划
|
SQL 关系型数据库 Java
关键时刻HINT出彩 - PG优化器的参数优化、执行计划固化CASE
背景 有过数据库使用经验的童鞋可曾遇到过SQL执行计划不准确,或者SQL执行计划抖动的问题。 PostgreSQL的执行计划与大多数的企业数据库是一样的,都是基于成本优化。 基于成本优化的优化器,在算法靠谱,统计信息准确的前提下,通常得到的执行计划是比较准确的。 那么什么时候执行
6828 0
|
关系型数据库 数据库 PostgreSQL
|
SQL Oracle 关系型数据库
【DBAplus】深入Oracle优化器:一条诡异执行计划的解决之道
深入Oracle优化器:一条诡异执行计划的解决之道 DBAplus社群 | 2016-05-05 19:51 CBO计算成本并选择最佳执行计划的至关重要输入物就是表和索引的统计信息,过旧或错误的统计信息则可能导致一个性能极差的执行计划被错误地选中。
1226 0
|
SQL MySQL 关系型数据库
MySQL之SQL分析三部曲实际案例(五)--临时表,优化器的选择
-------------------------------------------------------------------------------------------------正文-----------------------------------...
1105 0
|
SQL Oracle 关系型数据库
使用优化器性能视图获取SQL语句执行环境
    Oracle SQL语句的运行环境分为多个不同的层次,主要包括实例级别,会话级别,语句级别,其优先级依次递增。即语句级别的执行环境具有最高的优先权,会话级别次之,实例级别最低。
869 0
下一篇
DataWorks