优化器跟踪分析一个很怪异的现象

工作中遇到一则很奇怪的真实案例,有一个统计sql,统计结果在190-200之间时,耗时基本上维持在1.6S,统计结果在此数据范围外的统计耗时,基本上维持在0.1-0.3S之间,

按照惯例,explain查看执行计划。

为方便阐述,约定如下 :

数据范围在190-200,耗时1.6S的叫 sql1,数据范围不在此范围,耗时0.1-0.3S的叫sql2

sql1执行计划:

sql2执行计划:

两条完全相同的sql就筛选条件中换了一个departid的值,sql1 191条记录,sql2 256条记录,把sql2的departid换成一个记录数比较多或者比较少的时候,执行计划都不变。

为什么唯独190-200条记录之前,mysql会采用不同的索引呢?

为了搞清楚这个问题,借用optimizer trace功能

mysql默认不开启优化器跟踪功能,开启方法如下

set gloal optimizer_tracer=‘enabled=on,one_line=on‘; # 开启优化器跟踪,并只记录最后一条sql的跟踪。关闭将两个on修改成off即可

查询优化器的信息:

select trace from information_schema.optimizer_trace

执行过程中发现trace字段记录不全,可通过调大参数optimizer_trace_max_mem_size来设置

以下是sql1和sql2的部分trace信息

sql1

sql2

上述trace可以看出,SQL1优化器内部评估cost=249.6是成本最小的执行计划,走idx_duura索引,access_type采用了ref,sql2优化内部评估302.4是成本最低的走了idx_duur索引,access_type采用了range,本来sql2的应该是ref,但是优化器认为采用range会使用上index上更多的索引键(“users_more_keyparts”),这是mysql自身的优化。

在回到上面的执行计划,sql1的key_len=46,ref=const,const,const,46是怎么得来的呢。下面给出计算公式:

表结构:

索引idx_duura

索引idx_duur

sql中where条件用到了delete_flag,user_mode,user_type,ruleid

sql1执行计划中的key_len计算方法:1 * 3 + 2 + 10 * 3 + 1 + 2 + 2 * 3 + 2 = 46,用到了三个值,与ref=const,const,const相符

sql2执行计划中的key_len计算方法:1 * 3 + 2 + 10 * 3 + 1 + 2 + 2 * 3 + 2  + 40 * 3 + 2 = 168,同时使用了四个字段,过滤性更好。

以上已经知道了这怪异现象的原因,那应该如何解决呢?

1,根据实际业务场景考虑是否使用force index

2,结合业务修改sql

原文地址:https://www.cnblogs.com/jandison/p/9369099.html

时间: 2024-11-08 12:17:20

优化器跟踪分析一个很怪异的现象的相关文章

实验作业:使gdb跟踪分析一个系统调用内核函数

实验作业:使gdb跟踪分析一个系统调用内核函数(我使用的是getuid) 20135313吴子怡.北京电子科技学院 [第一部分] 根据视频演示的步骤,先做第一部分,步骤如下 ①更新menu代码到最新版 ②在代码中加入C函数.汇编函数 ③在main函数中加入makeconfig ④make rootfs ⑤可以看到qemu中增加了我们先前添加的命令: ⑥分别执行新增的命令 [第二部分]gdb跟踪分析一个系统调用内核函数 ①进入gdb调试 ②设置断点,继续执行: ③相对应的得到这样的结果: ④查看我

【2016.3.19】作业 分析一个很有(wu)趣(liao)的小程序

问题1:这个程序要找的是符合什么条件的数? 能够整除2-32中所有数仅除了在此之中的两个相邻的数,比如能整除2-29,且不能整除30,31.当然,这只是举个例子. 问题2:这样的数存在么?符合这一条件的最小的数是什么? 不知道是否存在,反正用z3735f跑了一个多小时没算出来,要算出来,估计得用超算.自己尝试算了一下2-15,2-20 都算出来了,但是再往后就费劲了.因为我不知道这个数在什么地方,因此假设他在整个搜索范围的前0.1%出现,我1.33GHZ双核的小电脑得跑好几百年....so,怒扔

Oracle 优化器

http://blog.csdn.net/it_man/article/details/8185370一.优化器基本知识 Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行.分析语句的执行计划的工作是由优化器(Optimizer)来完成的.不同的情况,一条SQL可能有多种执行计划,但在某一时点,一定只有一种执行计划是最优的,花费时间是最少的. 相信你一定会用Pl/sql Developer.Toad等工具去看一个语句的执行计划,不过你可能对Rule.Choos

Oracle优化器和优化模式

Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行.分析语句的执行计划的工作是由优化器(Optimizer) 来完成的.不同的情况,一条SQL可能有多种执行计划,但在某一时点,一定只有一种执行计划是最优的,花费时间是最少的.相信你一定会用Pl/sql Developer.Toad等工具去看一个语句的执行计划,不过你可能对Rule.Choose.First rows.All rows这几项有疑问,因为我当初也是这样的,那时我也疑惑为什么选了以上的不同的项,执行计

PostgreSQL 优化器代码概览

简介PostgreSQL 的开发源自上世纪80年代,它最初是 Michael Stonebraker 等人在美国国防部支持下创建的POSTGRE项目.上世纪末,Andrew Yu 等人在它上面搭建了第一个SQL Parser,这个版本称为Postgre95,也是加州大学伯克利分校版本的PostgreSQL的基石[1]. 我们今天看到的 PostgreSQL 的优化器代码主要是 Tom Lane 在过去的20年间贡献的,令人惊讶的是这20年的改动都是持续一以贯之的,Tom Lane 本人也无愧于"

Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程

陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux系统的一般执行过程 最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程 1. 正在运行的用户态进程X 2. 发生中断——save cs:eip/esp/eflags(current) to kernel stack, then load cs:eip(entry of a specific IS

实验八——理解进程调度时机跟踪分析进程调度与进程切换的过程

理解进程调度时机跟踪分析进程调度与进程切换的过程 攥写人:李鹏举  学号:20132201 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000) 一.实验要求: 理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否准确: 使用gdb跟踪分析一个schedule()函数 ,验

linux内核分析 第八周 理解进程调度时机跟踪分析进程调度与进程切换的过程

笔记: 实验:使用gdb跟踪分析一个schedule()函数

Linux内核分析--理解进程调度时机、跟踪分析进程调度和进程切换的过程

ID:fuchen1994 姓名:江军 作业要求: 理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否准确: 使用gdb跟踪分析一个schedule()函数 ,验证您对Linux系统进程调度与进程切换过程的理解:推荐在实验楼Linux虚拟机环境下完成实验. 特别关注并仔细分析switch_to中的汇编代码,理解进程上下文的切换机制,以及与中断上下文切换的关系: 实验过程: 1. 进程调度的时机 中断