mysql的trace追踪SQL工具,进行sql优化

news2024/9/27 19:18:02

trace是MySQL5.6版本后提供的SQL跟踪工具,通过使用trace可以让我们明白optimizer(优化器)如何选择执行计划。

注意:开启trace工具会影响mysql性能,所以只适合临时分析sql使用,用完之后请立即关闭。

测试数据脚本:

DROP TABLE IF EXISTS `t_student`;
CREATE TABLE `t_student` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `std_name` varchar(30) NOT NULL,
  `age` tinyint(3) unsigned NOT NULL,
  `class_id` int(11) unsigned NOT NULL,
  `gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_std_age` (`age`),
  KEY `idx_std_name_age_class` (`std_name`,`age`,`class_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=100766 DEFAULT CHARSET=utf8mb4;
 
--添加测试数据的存储过程

DROP PROCEDURE IF EXISTS proc_insert_student; 
DELIMITER $$
CREATE PROCEDURE proc_insert_student()        
BEGIN
  DECLARE i INT;                   
  SET i=1;                          
  WHILE i<=100000 DO                 
    INSERT INTO t_student(std_name,age,class_id) VALUES(CONCAT('Li Lei',i), (i MOD 120)+1 ,(i MOD 3)+1);   
    SET i=i+1;                       
  END WHILE;
END $$
 
-- 执行存储过程
call proc_insert_student();

trace工具用法

一.查看trace开关状态,默认关闭的

show variables like 'optimizer_trace';

二.开启face

1.会话级别临时开启,只在当前会话生效。

set session optimizer_trace="enabled=on",end_markers_in_json=on;

2.永久开启(重启失效)

注意用完关闭

set optimizer_trace="enabled=on";

三.用法

1.在查询sql后加上固定sql,例:

set session optimizer_trace="enabled=on",end_markers_in_json=on;  
select * from t_student where std_name > 'a' order by age;
SELECT * FROM information_schema.OPTIMIZER_TRACE;

2.查看执行计划,并未使用到联合索引,联合索引name使用的范围查询,一般都不会用到索引。 如果用name索引需要遍历name字段联合索引树,然后还需要根据遍历出来的主键值去主键索引树里再去查出最终数据,成本比全表扫描还高 。

EXPLAIN SELECT * FROM t_student WHERE std_name > 'a' ORDER BY age;

EXPLAIN SELECT std_name,age,class_id FROM t_student WHERE std_name > 'a' ORDER BY age;

3。如果查询是联合索引字段,那就使用了覆盖索引,这样的name范围查询,联合索引才会使用到,这样只需要遍历name字段的联合索引树就能拿到所有结果,叶子节点只存放二级索引的数据,这就不用回表操作。

TRACE列的json数据拷贝出来查看。主要是看cost值,成本

SELECT * FROM information_schema.OPTIMIZER_TRACE;
{
  "steps": [
    {
      "join_preparation": {  -- 第一阶段:SQL准备阶段,格式化sql
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `t_student`.`id` AS `id`,`t_student`.`std_name` AS `std_name`,`t_student`.`age` AS `age`,`t_student`.`class_id` AS `class_id`,`t_student`.`gmt_create` AS `gmt_create` from `t_student` where (`t_student`.`std_name` > 'a') order by `t_student`.`age`"
          }
        ] /* steps */
      } /* join_preparation */
    },
    {
      "join_optimization": {  -- 第二阶段:SQL优化阶段
        "select#": 1,
        "steps": [
          {
            "condition_processing": {  -- 条件处理
              "condition": "WHERE",
              "original_condition": "(`t_student`.`std_name` > 'a')",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "(`t_student`.`std_name` > 'a')"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "(`t_student`.`std_name` > 'a')"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "(`t_student`.`std_name` > 'a')"
                }
              ] /* steps */
            } /* condition_processing */
          },
          {
            "substitute_generated_columns": {
            } /* substitute_generated_columns */
          },
          {
            "table_dependencies": [  -- 表依赖详情
              {
                "table": "`t_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": "`t_student`",
                "range_analysis": {
                  "table_scan": {   -- 全表扫描
                    "rows": 100300,  -- 行数
                    "cost": 20351  -- 查询消耗
                  } /* table_scan */,
                  "potential_range_indexes": [  -- 查询可能使用的索引
                    {
                      "index": "PRIMARY",  -- 主键索引
                      "usable": false,  -- 未使用
                      "cause": "not_applicable"  -- 原因:不适合
                    },
                    {
                      "index": "idx_std_age",  -- age索引
                      "usable": false,  -- 未使用
                      "cause": "not_applicable"  -- 原因:不适合
                    },
                    {
                      "index": "idx_std_name_age_class",  -- stdname,age,class的组合索引
                      "usable": true,  -- 使用
                      "key_parts": [
                        "std_name",
                        "age",
                        "class_id",
                        "id"
                      ] /* key_parts */
                    }
                  ] /* potential_range_indexes */,
                  "setup_range_conditions": [
                  ] /* setup_range_conditions */,
                  "group_index_range": {  -- group 用到的索引
                    "chosen": false,  -- 未使用
                    "cause": "not_group_by_or_distinct"  -- 原因:未使用group by 或者 distinct
                  } /* group_index_range */,
                  "analyzing_range_alternatives": {   -- 分析各个索引使用成本
                    "range_scan_alternatives": [
                      {
                        "index": "idx_std_name_age_class",
                        "ranges": [
                          "a < std_name"  -- 索引使用范围
                        ] /* ranges */,
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,  -- 使用该索引获取的记录是否按照主键排序
                        "using_mrr": false,
                        "index_only": false,  -- 是否使用覆盖索引
                        "rows": 50150,  -- 索引扫描行数
                        "cost": 60181,   -- 索引使用成本
                        "chosen": false,  -- 是否选择该索引:否
                        "cause": "cost"  -- 原因:消耗
                      }
                    ] /* range_scan_alternatives */,
                    "analyzing_roworder_intersect": {  -- 分析使用索引合并的成本
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    } /* analyzing_roworder_intersect */
                  } /* analyzing_range_alternatives */
                } /* range_analysis */
              }
            ] /* rows_estimation */
          },
          {
            "considered_execution_plans": [  -- 分析出的执行计划
              {
                "plan_prefix": [
                ] /* plan_prefix */,
                "table": "`t_student`",
                "best_access_path": {  -- 最优访问路径
                  "considered_access_paths": [  --分析出的最终访问路径
                    {
                      "rows_to_scan": 100300,
                      "access_type": "scan",  -- 访问类型:为scan,全表扫描
                      "resulting_rows": 100300,
                      "cost": 20349,
                      "chosen": true,  -- 确定选择
                      "use_tmp_table": true
                    }
                  ] /* considered_access_paths */
                } /* best_access_path */,
                "condition_filtering_pct": 100,
                "rows_for_plan": 100300,
                "cost_for_plan": 20349,
                "sort_cost": 100300,
                "new_cost_for_plan": 120649,
                "chosen": true
              }
            ] /* considered_execution_plans */
          },
          {
            "attaching_conditions_to_tables": {   -- 为查询的表添加条件
              "original_condition": "(`t_student`.`std_name` > 'a')",
              "attached_conditions_computation": [
              ] /* attached_conditions_computation */,
              "attached_conditions_summary": [    -- 添加条件结果
                {
                  "table": "`t_student`",
                  "attached": "(`t_student`.`std_name` > 'a')"
                }
              ] /* attached_conditions_summary */
            } /* attaching_conditions_to_tables */
          },
          {
            "clause_processing": {   -- order by 处理
              "clause": "ORDER BY",
              "original_clause": "`t_student`.`age`",
              "items": [
                {
                  "item": "`t_student`.`age`"
                }
              ] /* items */,
              "resulting_clause_is_simple": true,
              "resulting_clause": "`t_student`.`age`"
            } /* clause_processing */
          },
          {
            "reconsidering_access_paths_for_index_ordering": {    -- 重构索引处理顺序
              "clause": "ORDER BY",
              "steps": [
              ] /* steps */,
              "index_order_summary": {
                "table": "`t_student`",
                "index_provides_order": false,
                "order_direction": "undefined",
                "index": "unknown",
                "plan_changed": false
              } /* index_order_summary */
            } /* reconsidering_access_paths_for_index_ordering */
          },
          {
            "refine_plan": [
              {
                "table": "`t_student`"
              }
            ] /* refine_plan */
          }
        ] /* steps */
      } /* join_optimization */
    },
    {
      "join_execution": {    -- 第三阶段:SQL执行阶段
        "select#": 1,
        "steps": [
          {
            "filesort_information": [
              {
                "direction": "asc",
                "table": "`t_student`",
                "field": "age"
              }
            ] /* filesort_information */,
            "filesort_priority_queue_optimization": {
              "usable": false,
              "cause": "not applicable (no LIMIT)"
            } /* filesort_priority_queue_optimization */,
            "filesort_execution": [
            ] /* filesort_execution */,
            "filesort_summary": {
              "rows": 100000,
              "examined_rows": 100000,
              "number_of_tmp_files": 14,
              "sort_buffer_size": 262016,
              "sort_mode": "<sort_key, packed_additional_fields>"
            } /* filesort_summary */
          }
        ] /* steps */
      } /* join_execution */
    }
  ] /* steps */
}

MySQL认为 全表扫描的成本低于索引扫描,所以mysql最终选择全表扫描,

4.关闭trace

 set session optimizer_trace="enabled=off";    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1507075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑中缺失EMP.dll文件怎么办,解决EMP.dll丢失问题的有效方法分享

当你的电脑出现由于找不到emp.dll无法继续执行代码的提示&#xff0c;那你要怎么办呢&#xff1f;其实解决方法还是挺多的&#xff0c;今天就来给大家详细的说说emp.dll这方面的信息吧。 一、电脑为什么会出现emp.dll丢失 不完全卸载软件&#xff1a;在卸载程序时&#xff0c;…

小迪安全37WEB 攻防-通用漏洞XSS 跨站权限维持钓鱼捆绑浏览器漏洞

#XSS跨站系列内容:1. XSS跨站-原理&分类&手法 XSS跨站-探针&利用&审计XSS跨站另类攻击手法利用 XSS跨站-防御修复&绕过策略 #知识点&#xff1a; 1、XSS 跨站-另类攻击手法分类 2、XSS 跨站-权限维持&钓鱼&浏览器等 1、原理 指攻击者利用…

可商用的HuoCMS建站系统,基于thinkphp内核且免费开源

HuoCMS是一套内容管理系统&#xff0c;同时也是一套适用于企业官网建设的系统&#xff0c;能够帮助用户快速搭建个人网站。满足企业站、外贸站、个人博客等多种建站需求。HuoCMS的优势在于可以通过统一后台管理多个网站的内容&#xff0c;方便维护和共享不同内容在不同网站上的…

关于playbook中when条件过滤报The conditional check ‘result|failed‘ failed的问题

问题现象 在使用plabook中的when做过滤脚本如下&#xff1a; --- - hosts: realserversremote_user: roottasks:- name: Check if httpd service is runningcommand: systemctl status httpdregister: resultignore_errors: True- name: Handle failed service checkdebug:ms…

离线数仓(六)【ODS 层开发】

前言 1、ODS 层开发 ODS层的设计要点如下&#xff1a; &#xff08;1&#xff09;ODS层的表结构设计依托于从业务系统同步过来的数据结构&#xff08;JSON/CSV/TSV&#xff09;。 &#xff08;2&#xff09;ODS层要保存全部历史数据&#xff0c;故其压缩格式应选择高压缩比的…

Android 学习之追踪应用的安装情况

先上结论&#xff0c;急用的话直接看结论 结论一、借助 API 读取安装信息&#xff0c;然后上报二、借助手动埋点&#xff0c;然后上报三、对比 前提过程 结论 一、借助 API 读取安装信息&#xff0c;然后上报 通过 PackageManager 的 API&#xff0c;我们可以得知自身应用安装…

基于VSCode安装Node.js开发环境

根据官网介绍&#xff0c;Node.js 是一个免费的、开源的、跨平台的JavaScript实时运行环境&#xff0c;允许开发人员在浏览器之外编写命令行工具和服务器端脚本. Node.js框架由于是采用JavaScript语法进行调用的&#xff0c;因此Node.js环境除了用来编写调试Node.js代码&#…

2024 年排名前 5 名的 Mac 数据恢复软件分享

如果您已经在 Mac 上丢失了数据并且正在寻找恢复数据的方法&#xff0c;那么您来对地方了。互联网上有超过 50 个适用于 Mac 的数据恢复程序。哪个是最好的 Mac 数据恢复软件&#xff1f;不用担心。本文列出了 5 款 Mac 数据恢复软件&#xff0c;可帮助您在 Mac OS 下恢复丢失的…

jvm八股

文章目录 运行时数据区域Java堆对象创建对象的内存布局对象的访问定位句柄直接指针 GC判断对象是否已死引用计数算法可达性分析算法 引用的类别垃圾收集算法分代收集理论标记清除算法标记复制算法标记整理算法 实现细节并发的可达性分析 垃圾收集器serial收集器ParNew收集器Par…

手机短信恢复 - 如何在 Android 手机上恢复删除的短信

手机每天发送和接收的短信数以亿计&#xff0c;而Android消息丢失每天都在发生。 Android短信恢复对于那些在设备中保存了一些重要信息的人来说显得至关重要。首先&#xff0c;我们向您推荐奇客数据恢复安卓版&#xff0c;这款软件能够高效、安全地恢复已删除的短信&#xff0…

结构指针的使用

结构指针的使用 指针类型变量&#xff1a; 指针类型&#xff0c;是变量类型的一种&#xff0c;它是专门用来存储变量的地址的。 例如 int *p; 表示p是一个指针变量&#xff0c;它用来存储某个整型变量的地址。 int a5; int *p&a; 这样&#xff0c;就将整型变量a的地…

有什么针对新闻媒体行业的安全解决方案

对媒体行业而言&#xff0c;门户网站是最易受到攻击的地方。常见的攻击方式有网页篡改、挂马和被植入暗链等。门户网站作为新闻媒体对外的第一扇门&#xff0c;通常承载了大量的流量&#xff0c;一旦遭到攻击&#xff0c;造成的影响会更具有可怕的“传播力”。那么我们应该如何…

Tree Shaking:优化前端项目的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

1、功能安全入门之内功心法ISO26262介绍

目录 0. 对于安全规范的认知 0.1 ISO26262简介 0.2 功能安全的必要性 2. ISO26262第1部分基本术语 2. ISO26262第2部分-功能安全管理 3. ISO26262第3部分-概念阶段 4. ISO26262第4部分-产品开发:系统层面 5. ISO26262第5部分-产品开发:硬件层面 6. ISO26262第6部分-…

使用VBA快速梳理多层级族谱(组织架构)

实例需求&#xff1a;族谱&#xff08;或者公司组织架构等&#xff09;都是典型的带有层级关系数据&#xff0c;例如下图中左侧表格所示。 A列为层级&#xff08;准确的讲是B列成员的层级&#xff09;&#xff0c;从一开始递增B列和C列为成员直接的父&#xff08;/母&#xff…

搭建一款实用的个人IT工具箱——it-tools

一、it-tools介绍 IT-Tools是一款开源的个人工具箱&#xff0c;专为IT从业人员打造&#xff0c;支持Docker私有化部署&#xff0c;包含众多实用的IT工具。其功能丰富多样&#xff0c;涵盖二维码生成、数据格式转换、MAC地址生成等&#xff0c;可满足用户多样化的需求。 二、本…

armv8/armv9 MMU深度学习

目录 1、MMU概念介绍2、虚拟地址空间和物理地址空间2.1、(虚拟/物理)地址空间的范围2.2、物理地址空间有效位(范围)2.2.1、页表翻译相关寄存器的配置 3、Translation regimes4、地址翻译/几级页表&#xff1f;4.1、思考&#xff1a;页表到底有几级&#xff1f;4.2、以4KB granu…

《日期类》的模拟实现

目录 前言&#xff1a; 头文件类与函数的定义Date.h 实现函数的Date.cpp 测试Test.cpp 运行结果&#xff1a; 前言&#xff1a; 我们在前面的两章初步学习认识了《类与对象》的概念&#xff0c;接下来我们将实现一个日期类&#xff0c;是我们的知识储备更加牢固。 头文件…

Android Gradle 开发与应用 (五) : 基于Gradle 8.2,创建Gradle插件

1. 前言 本文介绍在Android中&#xff0c;如何基于Gradle 8.2&#xff0c;创建Gradle插件。 1.1 本文环境 Android Studio 版本 : Android Studio Hedgehog | 2023.1.1Gralde版本 : gradle 8.2 使用 Android Gradle 插件升级助理 Android Gradle 插件版本说明 1.2 为什么要写…

【C语言】——详解操作符(下)

【C语言】——详解操作符&#xff08;下&#xff09; 前言七、关系操作符八、逻辑操作符8.1、& 与运算符8.2、 | 或运算符 九、条件操作符十、逗号表达式十一、下标引用与函数调用操作符11.1、[ ] 下标引用操作符11.2、( ) 函数调用操作符 十二、 结构成员操作符12.1、…