开发同事问,为什么一个标量子查询,放在where子句后进行大小判断,比不放在where子句后进行判断大小运行的更快?按道理加了一次判断,不是应该变慢么?

把语句拿过来,看了一下两个语句的执行计划:

语句1和执行计划1:

SELECT A.*,
/*剩余量*/
(A.q_basic -
(SELECT COALESCE(SUM(d.q_basic), 0.00)
FROM e_order d
WHERE CAST(d.r_item AS INT) = A.ID
AND d.req_status NOT IN ('FZ'))) AS surplus
FROM e_order A
LEFT JOIN e_requirement b
ON A.requirement_no = b.requirement_no
LEFT JOIN erp_project C
ON b.factory = C.project_no
WHERE 1 = 1
AND A.status IN ('WC')
AND (A.q_basic -
(SELECT COALESCE(SUM(d.q_basic), 0.00)
FROM e_order d
WHERE CAST(d.r_item AS INT) = A.ID
AND d.req_status NOT IN ('FZ'))) > 0.00
AND (C.project_name LIKE CONCAT('%', 'csg18098', '%') OR
C.project_no LIKE CONCAT('%', 'csg18098', '%'))
AND A.requirement_no LIKE CONCAT('%', '0000004390', '%');

语句2和执行计划2:

SELECT A.*,
/*剩余量*/
(A.q_basic -
(SELECT COALESCE(SUM(d.q_basic), 0.00)
FROM e_order d
WHERE CAST(d.r_item AS INT) = A.ID
AND d.req_status NOT IN ('FZ'))) AS surplus
FROM e_order A
LEFT JOIN e_requirement b
ON A.requirement_no = b.requirement_no
LEFT JOIN erp_project C
ON b.factory = C.project_no
WHERE 1 = 1
AND A.status IN ('WC')
AND (C.project_name LIKE CONCAT('%', 'csg18098', '%') OR
C.project_no LIKE CONCAT('%', 'csg18098', '%'))
AND A.requirement_no LIKE CONCAT('%', '0000004390', '%')

从上面的执行计划看,在where之后进行大小判断后,执行时间是662.954 ms;去掉判断后执行时间是1549.644 ms。的确如开发所说。

现在分别来看上面的两个执行计划。
语句1在where子句后增加判断,表关联的顺序是((((a,d_1),b),c),d)。语句2不在where子句后加判断的关联顺序是(((a,b),c),d)。

其实这里d_1就是表示在where子句后的表e_order。这一点,可以将语句修改一下,就可以得到验证:

SELECT A.*,
/*剩余量*/
(A.q_basic -
(SELECT COALESCE(SUM(d.q_basic), 0.00)
FROM e_order d
WHERE CAST(d.r_item AS INT) = A.ID
AND d.req_status NOT IN ('FZ'))) AS surplus
FROM e_order A
LEFT JOIN e_requirement b
ON A.requirement_no = b.requirement_no
LEFT JOIN erp_project C
ON b.factory = C.project_no
WHERE 1 = 1
AND A.status IN ('WC')
AND (A.q_basic -
(SELECT COALESCE(SUM(e.q_basic), 0.00)
FROM e_order e
WHERE CAST(e.r_item AS INT) = A.ID
AND e.req_status NOT IN ('FZ'))) > 0.00
AND (C.project_name LIKE CONCAT('%', 'csg18098', '%') OR
C.project_no LIKE CONCAT('%', 'csg18098', '%'))
AND A.requirement_no LIKE CONCAT('%', '0000004390', '%');

修改后,关联的顺序就是表关联的顺序是((((a,e),b),c),d)。故d_1就是表示在where子句后的表e_order。

回看执行计划1,可以看到很多关键字(never executed)。其实在执行计划1中,(a,d_1)两个表关联后,返回的行数是0,所以之后加入连接的表其实并未执行实际连接操作,即b,c,d并未真的执行join操作。这个语句执行(a,d_1)两个表关联后就结束了。

而在where子句后删除对子查询结果大小判断后,表的连接顺序是(((a,b),c),d)。从执行计划2中可以看到,每个表都参与的join操作后,整个语句才执行结束。因此,时间比第一个执行计划的时间长了。

这里,子查询结果判断后返回的结果是0行。如果,不是0行呢?
我们把语句1中>0.00换成=0.000000,看看执行计划:

这个执行计划3,就比执行计划1和执行计划2都慢了。

pg执行计划分析小笔记的更多相关文章

  1. SQLServer查询执行计划分析 - 案例

    SQLServer查询执行计划分析 - 案例 http://pan.baidu.com/s/1pJ0gLjP 包括学习笔记.书.样例库

  2. MySQL学习系列2--MySQL执行计划分析EXPLAIN

    原文:MySQL学习系列2--MySQL执行计划分析EXPLAIN 1.Explain语法 EXPLAIN SELECT …… 变体:   EXPLAIN EXTENDED SELECT …… 将执行 ...

  3. MongoDB执行计划分析详解

    要保证数据库处于高效.稳定的状态,除了良好的硬件基础.高效高可用的数据库架构.贴合业务的数据模型之外,高效的查询语句也是不可少的.那么,如何查看并判断我们的执行计划呢?我们今天就来谈论下MongoDB ...

  4. MySQL学习系列2--MySQL执行计划分析EXPLAIN [原创]

    1.Explain语法 EXPLAIN SELECT …… 变体:   EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可 ...

  5. MySQL执行计划分析

    原文:MySQL执行计划分析 一. 执行计划能告诉我们什么? SQL如何使用索引 联接查询的执行顺序 查询扫描的数据函数 二. 执行计划中的内容 SQL执行计划的输出可能为多行,每一行代表对一个数据库 ...

  6. MongoDB干货系列2-MongoDB执行计划分析详解(2)(转载)

    写在之前的话 作为近年最为火热的文档型数据库,MongoDB受到了越来越多人的关注,但是由于国内的MongoDB相关技术分享屈指可数,不少朋友向我抱怨无从下手. <MongoDB干货系列> ...

  7. oracle sql 执行计划分析

    转自http://itindex.net/detail/45962-oracle-sql-%E8%AE%A1%E5%88%92 一.首先创建表 SQL> show user USER is &q ...

  8. SQL执行计划分析

    explain执行计划中的字段以及含义在下面的博客中有详细讲述: https://blog.csdn.net/da_guo_li/article/details/79008016 执行计划能告诉我们什 ...

  9. mysql系列八、mysql数据库优化、慢查询优化、执行计划分析

    mysql的性能优化无法一蹴而就,必须一步一步慢慢来,从各个方面进行优化,最终性能就会有大的提升. 一.介绍 对mysql优化是一个综合性的技术,主要包括 表的设计合理化(符合3NF) 添加适当索引( ...

随机推荐

  1. Java开发环境之ElasticSearch

    查看更多Java开发环境配置,请点击<Java开发环境配置大全> 拾章:ElasticSearch安装教程 1)去官网下载ElasticSearch安装包 http://www.elast ...

  2. WSL quick overview

    简介 WSL,是Windows Subsystem for Linux的缩写,字面意义上理解就是WIndows下的Linux子系统.WSL 由Microsoft Windows内核团队创建,目前如果最 ...

  3. http上传下载文件

    curl_easy_setopt curl库的方式 调用 (c++中) 短连接  一次请求 一次响应

  4. 如果在使用谷歌的gson的时候,在返回时间类型的数据的时候,

    可能会出现在long类型的时间后面多3个0 如下图所示 可以自己创建一个json序列化的类 public class Date2LongSerializer extends JsonSerialize ...

  5. Vue的参数请求与传递

    Vue不同模板之间的参数传递 页面路由带参数的跳转: 参数接收: Vue向服务器请求资源的两种方式 VUE-RESOURCE 1.Vue.js是数据驱动的,这使得我们并不需要直接操作DOM,如果我们不 ...

  6. hiveSQL常用日期函数

    注意 MM,DD,MO,TU 等要大写 Hive 可以在 where 条件中使用 case when 已知日期 要求日期 语句 结果 本周任意一天 本周一 select date_sub(next_d ...

  7. fullcalendar + qTip2显示事件详情

    fullcalendar 是一个很优秀的日历插件.qTip2 是一个强大的提示工具.在讲下面的功能之前,需要对fullcalendar 和 qTip2 有些了解,可直接点击下面贴出的2个地址: ful ...

  8. puppeteer 试用

    puppeteer 是chrome 团队提供的Headless chrome node api 库,我们可以用来方便的进行chrome 操作,同时 可以做好多事情(web 爬虫,生成pdf,截图... ...

  9. Lightning Web Components 来自salesforce 的web 组件化解决方案

    Lightning Web Components 是一个轻量,快速,企业级别的web 组件化解决方案,官方网站也提供了很全的文档 对于我们学习使用还是很方便的,同时我们也可以方便的学习了解salesf ...

  10. mariadb启动不了

    提示地址已经被使用,是否有其他的进程正在使用 /var/run/sdata/mysql.sock 查询该文件,发现没有,sdata目录都不存在,应该是上次mysql意外关闭导致这个目录丢失了, 使用r ...