一个复杂子查询SQL优化

作者:网络    软件教程库   2020-05-18

select *
  from test.vmark vk
 where id in (select v.id
                from usr_center.vmark_degree_update_log v, (select min(id) id
                        from usr_center.vmark_degree_update_log
                       where degree_update_cause = 0
                         and degree_update_type = 0
                       group by user_id) log               where v.id = log.id
                 and v.degree_update_type = 0
                 and v.degree_update_before between ‘2015-01-01 00:00:00‘ and

‘2015-01-10 00:00:00‘);

#43;----#43;--------------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;------#43;----------#43;----------------------------------------------#43;
| id | select_type        | table                   | type   | possible_keys  | key     | key_len | ref  | rows     | extra                                        |
#43;----#43;--------------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;------#43;----------#43;----------------------------------------------#43;
|  1 | primary            | vk                      | all    | null           | null    | null    | null | 66051213 | using where                                  ||  2 | dependent subquery | derived3              | all    | null           | null    | null    | null |    82947 | using where                                  |
|  2 | dependent subquery | v                       | eq_ref | primary,idx_dd | primary | 4       | func |        1 | using where                                  ||  3 | derived            | vmar_degree_update_log | ref    | idx_dd         | idx_dd  | 1       |      | 12508106 | using where; using temporary; using filesort |
#43;----#43;--------------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;------#43;----------#43;----------------------------------------------#43;
4 rows in set (8.10 sec)


怎么解读这个执行计划呢?

1.首先执行id=3的标识为derived的步骤,这个关键词是衍生,出现在from后的子查询会有这个标识。

索引idx_dd(degree_update_type,degree_update_after)将被用于这一步,ref表名这是非唯一索引扫描,预计扫描12287942行。

2.执行id=2的第一条计划,也就是将第id=4的结果,group by成的82946行,对这个临时表做一个全表扫描。这里dependent subquery的意思是,这里要扫描的行数或执行次数,取决于其他步骤,即依赖于第4步。这里扫描82946行。

3.得到log.id信息后,根据v.id=log.id,去驱动v表,走的是primary,eq_ref也反映这是唯一索引扫描,从rows可以看出,每执行一次返回1行,执行多少次呢,执行82946次,因为是dependent subquery,所以执行次数或扫描行数依赖于第2步,也就是第2步每扫出一条,第3步就走一次索引。这里我们也看出来了,mysql的执行计划并不是反映最终返回几行,不是反映这步骤总共扫描几行,也不告诉你执行多少次,而只是返回执行一次返回多少行。这里扫描82946行。

4.全表扫描test.vmar表,66050840行,然后nest loop join之前步骤返回的结果集(实际有8万多行)。这一步骤最耗时,读66050840*80000行。

这里扫描行数成本是:12287942#43;82946*2#43;66050840*80000=7263409280000,7千亿行,我假设1亿行读20分钟,也需要2300多个小时,这个执行计划很恐怖。

结论:放在from的子查询是非关联子查询,没关系。但是放在where后的,却要紧。


问题出在第4步,test.vmark表实际上id上有主键索引,我们如果能用前面三步的结果集,获得id#20540;,再去驱动test.vmark的id#20540;,那么就很容易得到想要的结果。


更改sql如下,将in转变成join。

select *
  from test.vmar vk join (select v.id
                from usr_center.vmar_degree_update_log v,
                     (select min(id) id
                        from usr_center.vmar_degree_update_log
                       where degree_update_cause = 0
                         and degree_update_type = 0
                       group by user_id) log
               where v.id = log.id
                 and v.degree_update_type = 0
                 and v.degree_update_before between ‘2015-01-01 00:00:00‘ and
                     ‘2015-01-10 00:00:00‘) child
                  where vk.id = child.id;
#43;----#43;-------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;----------#43;----------#43;----------------------------------------------#43;
| id | select_type | table                   | type   | possible_keys  | key     | key_len | ref      | rows     | extra                                        |
#43;----#43;-------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;----------#43;----------#43;----------------------------------------------#43;
|  1 | primary     | derived2              | all    | null           | null    | null    | null     |    82371 |                                              |
|  1 | primary     | vk                      | eq_ref | primary        | primary | 4       | child.id |        1 |                                              |
|  2 | derived     | derived3              | all    | null           | null    | null    | null     |    82948 |                                              |
|  2 | derived     | v                       | eq_ref | primary,idx_dd | primary | 4       | log.id   |        1 | using where                                  |
|  3 | derived     |  vmar_degree_update_log | ref    | idx_dd         | idx_dd  | 1       |          | 11901368 | using where; using temporary; using filesort |
#43;----#43;-------------#43;-------------------------#43;--------#43;----------------#43;---------#43;---------#43;----------#43;----------#43;----------------------------------------------#43;
这个执行计划的解释,前面几步,也就是对应这个执行计划的第3,4,5行都比较像,就不再累述。得到的结果集有id#20540;,第一行的执行计划就读这个结果集,有82371行,读出的每一行取出id#20540;去驱动test.vmark表的主键id。

这里读取行数的成本是:11901368#43;82948*2#43;82371*2=48102006行。


一个复杂子查询sql优化

原文地址:http://blog.csdn.net/whiteoldbig/article/details/45437573

以上就是由(软件教程库https://www.itjcku.com/9999/1091480.html)本站为大家整理

阅读全部内容


Tags:一个复杂繁杂查询优化

返回首页



推荐内容

Java多线程中常见的几个问题

我们都知道,在java中要想实现多线程,有两种手段,一种是继续thread类,另外一种是实现runable接口。  1. ...

OracleDataIntegrator12c-CreatingaCollocatedAgent

http://www.oracle.com/webfolder/technetwork/tutorials/obe/fm ...

CompilingGCC5onOSX

compiling gcc 5 on os x */--> pre.src {backgro ...

查看Linux上MySQL版本信息

如果mysql是用rpm或者yum安装的,可用 #rpm -qa|grep mysql查看. 如: [[email#16 ...

《赢在测试2-中国软件测试专家访谈录》读书笔记

《赢在测试2-中国软件测试专家访谈录》读书笔记 2015-04-30 测试人物经历与观点 1.董杰 百度测试架构师 董杰 ...

Objective-C的KVC和KVO

字面意思分别是: kvc是指key value coding,键值编码。 kvo是指key value observin ...

20150502调试分析之使用gdb远程调试ARM开发板

20150502 调试分析之 使用gdb远程调试arm开发板 2015-05-02 lover雪儿 今天我们要学习 ...

限制Apache日志access.log文件大小

可以在apache的httpd.conf配置文件中配置apache自带的程序rotatelogs的功能。 rotate ...

UVa11561-GettingGold

题目:给你一个二维的地图,里面有陷阱‘t‘,金子‘g‘以及墙壁‘#‘,和普通的道路‘.‘,现在已知一个人在起点‘p‘; ...

configure:error:cannotcomputesuffixofobjectfiles:cannotcompile

centos 6.5下安装gcc-4.8.4 make的时候提示以下错误: configure: error: can ...

我读的第一本书《梦断代码》

一切都是兴趣所在,兴趣才是发展的动力,虽然我们在这个开发过程中不可否认的会遇到挫折、瓶颈,但我认为,地狱与天堂共存 ...

iOS中定时器NSTimer的使用

ios中定时器nstimer的使用 1、初始化 + (nstimer *)timerwithtimeinterval:( ...

数组遍历二叉

//任务二叉树遍历 void cmission::initmission(dword base) { cha ...

Oracle基础<1>--数据库设计

一:为什么需要使用数据库设计   数据库设计可以使数据库通过健壮的数据库结构 高效并且健康 的进行工作。 二.数据库设计 ...

LinuxShell之七函数应用

函数是什么?函数是一些命令的集合,使用一个名称做代表,称为函数名称。函数名称的命名规则和变量相同。一旦函数定义好了,执行 ...

SkillButton技能冷却

#pragmaonce #include"cocos2d.h" using_ns_cc; classskillbutto ...

sles11启用Xmanager

一:开启xmanager要满足一下2个条件:1.安装了gnome桌面环境,并且默认启动级别为52.ip地址为固定ip地址 ...

linux软件管理之rpm、yum

应用程序: 程序:architecturec语言:源代码——》(编译)二进制格式脚本:解释器(二进制程序)源代码——》编 ...

MyEclipse2014下搭建Android开发环境

1、下载android-sdk_r24.1.2-windows.zip,将其解压到一个文件夹中,例如:d:\progra ...

LinuxShell之八转向的用法

一、文件代码“转向”的意思是说:原本应由标准输入(如键盘)读取数据的,改由其它文件读取;原本应把结果显示在标准输出(如屏 ...

Java中有关null的9件事

java中有关 null 的9件事 对于java程序员来说,null是令人头痛的东西。时常会受到空指针异常(np ...

LDAP账号同步和Windows域集成验证

#65279;#65279; paradise.ezla.com.tw/files/article/html/32/32 ...

在同一个sql语句中如何写不同条件的count数量(转)

select sum(case when (t.条件字段=‘00‘) then 1 else 0 ...

详解MessageBox(),MsgBox函数的正确使用

//或者使用chr(13),chr(10)效果一样 msgbox aamp;chr(13)amp;bamp;chr( ...

swift学习笔记5

五、集合 数组 1、泛型 arraylt;类型gt; 2、简化[类型] var myar:arraylt;stringg ...

约在CBD,吃饭

午饭当然是外卖。 cbd上班的同仁们不用约,都去了一间叫大食堂的餐厅。 它在商业街繁华地段的二楼,有1000平米。你不知 ...

headFirst学习笔记之十:状态模式(5.2)

1.如何从状态图得到真正的代码: (1)找出所有状态:没有25分钱,有25分钱,糖果售罄,售出糖果。 (2)创建一个实例 ...

zabbixPHPdatabasessupportoffFail

zabbix初始化检查安装环境不通过: php databases support off fail --未找到所 ...

JS中字符串,数组常见操作

字符串mdash;mdash;mdash;》数组 abc =gt; ["a","b","c"]直接使用split方法 ...

IOS简单的动画自定义方法(旋转、移动、闪烁等)

#define kdegreestoradian(x) (m_pi * (x) /180.0) #define kra ...


本网站部分内容来自互联网,版权归原作者所有,文章内容仅代表原作者个人观点。如有侵权请联系我们删除 电子邮件 itjcku@foxmail.com