1、测试数据如下:

SQL> select * from t1;
  a | b  | c

---+----+---
  1 | 10 | 1
  2 | 20 | 2
  3 | 30 | 3
  4 | 40 | 4
  5 | 50 | 5
  6 | 60 | 6

(6 rows)

SQL> select * from t2;
  a | b  | d

---+----+---
  1 | 10 | 1
  2 | 20 | 2
  3 | 30 | 3

(3 rows)

2、解析示例SQL 如下 :

select *

from (

select * from t1 where c >= 2

) t1 left join (

select * from t2 where b < 30

) t2 on t1.a = t2.a

and t2.d > 1

where t1.b < 50

;

3、Oracle数据库查看执行结果及执行计划:

SQL> select *

from (

select * from t1 where c >= 2

) t1 left join (

select * from t2 where b < 30

) t2 on t1.a = t2.a

and t2.d > 1

where t1.b < 50

;

A        B           C      A         B        D

---------- ---------- ---------- ---------- ---------- ----------
      2       20           2      2        20        2
      3       30           3
      4       40           4

Execution Plan

----------------------------------------------------------

Plan hash value: 1823443478

---------------------------------------------------------------------------

| Id  | Operation       | Name | Rows  | Bytes | Cost (%CPU)| Time      |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |    3 |   234 |    7  (15)| 00:00:01 |

|*  1 |  HASH JOIN OUTER   |      |    3 |   234 |    7  (15)| 00:00:01 |

|*  2 |   TABLE ACCESS FULL| T1   |    3 |   117 |    3   (0)| 00:00:01 |

|*  3 |   TABLE ACCESS FULL| T2   |    1 |    39 |    3   (0)| 00:00:01 |

---------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - access("T1"."A"="T2"."A"(+))
    2 - filter("T1"."B"<50 AND "C">=2)
    3 - filter("T2"."D"(+)>1 AND "B"(+)<30)

Note

-----
    - dynamic sampling used for this statement (level=2)

Statistics

----------------------------------------------------------
       0  recursive calls
       0  db block gets
       7  consistent gets
       0  physical reads
       0  redo size
     926  bytes sent via SQL*Net to client
     523  bytes received via SQL*Net from client
       2  SQL*Net roundtrips to/from client
       0  sorts (memory)
       0  sorts (disk)
       3  rows processed

4、PGSQL数据库查看执行结果及执行计划:
      

postgres=# select *

postgres-# from (

postgres(# select * from t1 where c >= 2

postgres(# ) t1 left join (

postgres(# select * from t2 where b < 30

postgres(# ) t2 on t1.a = t2.a

postgres-# and t2.d > 1

postgres-# where t1.b < 50

postgres-# ;
  a | b  | c | a | b  | d

---+----+---+---+----+---
  2 | 20 | 2 | 2 | 20 | 2
  3 | 30 | 3 |   |    | 
  4 | 40 | 4 |   |    | 

(3 rows)

postgres=# explain analyze select *

postgres-# from (

postgres(# select * from t1 where c >= 2

postgres(# ) t1 left join (

postgres(# select * from t2 where b < 30

postgres(# ) t2 on t1.a = t2.a

postgres-# and t2.d > 1

postgres-# where t1.b < 50

postgres-# ;
                                                  QUERY PLAN                                                

------------------------------------------------------------------------------------------------------------
  Hash Left Join  (cost=37.04..85.88 rows=197 width=24) (actual time=0.020..0.027 rows=3 loops=1)
    Hash Cond: ("outer".a = "inner".a)
    ->  Seq Scan on t1  (cost=0.00..36.55 rows=197 width=12) (actual time=0.005..0.008 rows=3 loops=1)
          Filter: ((c >= 2) AND (b < 50))
    ->  Hash  (cost=36.55..36.55 rows=197 width=12) (actual time=0.006..0.006 rows=1 loops=1)
          ->  Seq Scan on t2  (cost=0.00..36.55 rows=197 width=12) (actual time=0.002..0.003 rows=1 loops=1)
                Filter: ((b < 30) AND (d > 1))
  Total runtime: 0.052 ms

(8 rows)

5、MySQL数据库查看执行结果及执行计划:
      

mysql> select *
     -> from (
     -> select * from t1 where c >= 2
     -> ) t1 left join (
     -> select * from t2 where b < 30
     -> ) t2 on t1.a = t2.a
     -> and t2.d > 1
     -> where t1.b < 50
     -> ;

+---+----+---+------+------+------+

| a | b  | c | a    | b    | d    |

+---+----+---+------+------+------+

| 2 | 20 | 2 |    2 |   20 |    2 |

| 3 | 30 | 3 | NULL | NULL | NULL |

| 4 | 40 | 4 | NULL | NULL | NULL |

+---+----+---+------+------+------+

3 rows in set (0.05 sec)

mysql> explain select *
     -> from (
     -> select * from t1 where c >= 2
     -> ) t1 left join (
     -> select * from t2 where b < 30
     -> ) t2 on t1.a = t2.a
     -> and t2.d > 1
     -> where t1.b < 50
     -> ;

+----+-------------+------------+------+---------------+-------------+---------+------+------+-------------+

| id | select_type | table      | type | possible_keys | key         | key_len | ref  | rows | Extra       |

+----+-------------+------------+------+---------------+-------------+---------+------+------+-------------+

|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL        | NULL    | NULL |    6 | Using where |

|  1 | PRIMARY     | <derived3> | ref  | <auto_key0>   | <auto_key0> | 8       | t1.a |    1 | Using where |

|  3 | DERIVED     | t2         | ALL  | NULL          | NULL        | NULL    | NULL |    3 | Using where |

|  2 | DERIVED     | t1         | ALL  | NULL          | NULL        | NULL    | NULL |    6 | Using where |

+----+-------------+------------+------+---------------+-------------+---------+------+------+-------------+

4 rows in set (0.00 sec)

6、针对以上SQL执行计划的分析:

1) 全表扫描左表T1,同时根据T1表子查询条件"C">=2和where过滤条件"T1"."B"<50联合过滤,即filter("T1"."B"<50 AND "C">=2),计算结果临时表记为tmp1;

2) 全表扫描右表T2,同时根据T2表子查询条件"B"(+)<30和on子句"T2"."D"(+)>1联合过滤,即filter("T2"."D"(+)>1 AND "B"(+)<30),计算结果临时表记为tmp2;

3) 左表T1及右表T2处理后临时表tmp1和tmp2通过access("T1"."A"="T2"."A"(+))连接条件进行Hash Left Join操作,左临时表结果集全量返回,右表不匹配行置为null,返回结果临时表记为tmp3;

4) 返回结果集。

7、一些更为复杂得SQL如下,有兴趣自行研究:

1) 测试数据

create table tmp1 as

select a,b,c,a as e from t1;

create table tmp2 as

select a,b,d,a as e from t2;

2) 示例SQL

select *

from (

select * from tmp1 where c >= 1

) t1 left join (

select * from tmp2 where b < 30

) t2 on t1.a = t2.a

and t2.d > 1 and t1.e >= 2

where t1.b < 50

;

select *

from (

select * from tmp1 where c >= 1

) t1 left join (

select * from tmp2 where b < 30

) t2 on t1.a = t2.a

and t2.d > 1 and t1.e >= 2

where t1.b < 50 and t2.e <= 3

;

一个RDBMS左连接SQL执行计划解析的更多相关文章

  1. 两个左连接SQL执行计划解析(Oracle和PGSQL对比):

    上一篇解析链接如下: https://www.cnblogs.com/wcwen1990/p/9325968.html 1.SQL示例1: SQL> select * from ( select ...

  2. Oracle sql执行计划解析

    Oracle sql执行计划解析 https://blog.csdn.net/xybelieve1990/article/details/50562963 Oracle优化器 Oracle的优化器共有 ...

  3. sql执行计划解析案例(二)

    sql执行计划解析案例(二)   今天是2013-10-09,本来以前自己在专注oracle sga中buffer cache 以及shared pool知识点的研究.但是在研究cache buffe ...

  4. 表连接sql执行计划学习

    循环嵌套连接(Nested Loop Join) 合并连接(Merge Join) 哈西匹配(Hash Join) 文章:浅谈SQL Server中的三种物理连接操作 循环嵌套,如果内循环列上有索引, ...

  5. oracle sql 执行计划分析

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

  6. [转载]循规蹈矩:快速读懂SQL执行计划的套路与工具

    作者介绍 梁敬彬,福富研究院副理事长.公司唯一四星级内训师,国内一线知名数据库专家,在数据库优化和培训领域有着丰富的经验.多次应邀担任国内外数据库大会的演讲嘉宾,在业界有着广泛的影响力.著有多本畅销书 ...

  7. 来自灵魂的拷问——知道什么是SQL执行计划吗?

    面试官说:工作这么久了,应该知道sql执行计划吧,讲讲Sql的执行计划吧! 看了看面试官手臂上纹的大花臂和一串看不懂的韩文,吞了吞口水,暗示自己镇定点,整理了一下思绪缓缓的对面试官说:我不会 面试官: ...

  8. Atitit sql执行计划

    Atitit sql执行计划 1.1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的 Oracle中的执行计划 ...

  9. Oracle之SQL优化专题01-查看SQL执行计划的方法

    在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...

随机推荐

  1. Ubuntu 16.04 总出现红色圆圈警告和检测到系统程序出现问题

    这种问题不可忽视!不可忽视!不可忽视!重要的事情说三遍!!!(一次死机,好多文件丢失,真是痛苦的经历) 自从从第三方安装了Python3.6,并将默认3.5改为3.6,导致ubuntu16.04右上角 ...

  2. WebService - [Debug] java.net.BindException: Can't assign requested address

    Connected to the target VM, address: '127.0.0.1:57803', transport: 'socket' Exception in thread &quo ...

  3. .Net IOC框架入门之三 Autofac

    一.简介   Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个 目的 1.依赖注入的目的是为了解耦. 2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置. 3.控制反转即 ...

  4. 行为驱动:Cucumber + Selenium + Java(一) - Cucumber简单操作实例

    场景(Scenarios) 场景是Cucumber结构的核心之一.每个场景都以关键字“Scenario:”(或本地化一)开头,后面是可选的场景标题.每个Feature可以有一个或多个场景,每个场景由一 ...

  5. C# 微信开发-----微信会员卡(二)

    主要说说如何使用微信的激活会员卡 如图: 点击激活会员卡时,要跳转到如下的图片: 要实现这个功能,首先我们在创建会员卡后就操作如下代码 #region 添加激活时的自定义字段 string custo ...

  6. pl/sql学习(5): 触发器trigger/事务和锁

    (一)触发器简单介绍 触发器是由数据库的特定时间来触发的, 特定事件主要包括以下几种类型: (1)DML: insert, update,delete 增删改 (2)DDL: create, alte ...

  7. LINUX常见性能监控工具总结

    文章来源 工具功能概览 整理了一个关于监控工具及其功能的表.下面对这些工具单独详细介绍. Linux性能监控工具 top top命令会展示进程的实际活动.默认情况下,它会列出系统上所有cpu密集型任务 ...

  8. jQuery的下拉选select2插件用法

    1转自:https://www.jb51.net/article/95561.htm 用了这么久的Select2插件,也该写篇文章总结总结.当初感觉Select2不是特别好用,但又找不到比它更好的下拉 ...

  9. “System.FormatException”类型的未经处理的异常在 System.IdentityModel.dll 中发生 其他信息: 十六进制字符串格式无效。

    如果你的 WebService 客户端证书配置都没问题,唯独调用接口会出现这个错误 “System.FormatException”类型的未经处理的异常在 System.IdentityModel.d ...

  10. scrapy_redis 相关: 将 jobdir 保存的爬虫进度转移到 Redis

    0.参考 Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误 1.说明 Scrapy 设置 jobdir,停止爬虫后,保存文件目录 ...