一个RDBMS左连接SQL执行计划解析
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执行计划解析的更多相关文章
- 两个左连接SQL执行计划解析(Oracle和PGSQL对比):
上一篇解析链接如下: https://www.cnblogs.com/wcwen1990/p/9325968.html 1.SQL示例1: SQL> select * from ( select ...
- Oracle sql执行计划解析
Oracle sql执行计划解析 https://blog.csdn.net/xybelieve1990/article/details/50562963 Oracle优化器 Oracle的优化器共有 ...
- sql执行计划解析案例(二)
sql执行计划解析案例(二) 今天是2013-10-09,本来以前自己在专注oracle sga中buffer cache 以及shared pool知识点的研究.但是在研究cache buffe ...
- 表连接sql执行计划学习
循环嵌套连接(Nested Loop Join) 合并连接(Merge Join) 哈西匹配(Hash Join) 文章:浅谈SQL Server中的三种物理连接操作 循环嵌套,如果内循环列上有索引, ...
- oracle sql 执行计划分析
转自http://itindex.net/detail/45962-oracle-sql-%E8%AE%A1%E5%88%92 一.首先创建表 SQL> show user USER is &q ...
- [转载]循规蹈矩:快速读懂SQL执行计划的套路与工具
作者介绍 梁敬彬,福富研究院副理事长.公司唯一四星级内训师,国内一线知名数据库专家,在数据库优化和培训领域有着丰富的经验.多次应邀担任国内外数据库大会的演讲嘉宾,在业界有着广泛的影响力.著有多本畅销书 ...
- 来自灵魂的拷问——知道什么是SQL执行计划吗?
面试官说:工作这么久了,应该知道sql执行计划吧,讲讲Sql的执行计划吧! 看了看面试官手臂上纹的大花臂和一串看不懂的韩文,吞了吞口水,暗示自己镇定点,整理了一下思绪缓缓的对面试官说:我不会 面试官: ...
- Atitit sql执行计划
Atitit sql执行计划 1.1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的 Oracle中的执行计划 ...
- Oracle之SQL优化专题01-查看SQL执行计划的方法
在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...
随机推荐
- L1-Day3
L1-Day31.太阳从西边落下. [我的翻译]The sun falls in the west. [标准答案]The sun sets in the west. [对比分析]落下fall与set的 ...
- Distance on the tree(数剖 + 主席树)
题目链接:https://nanti.jisuanke.com/t/38229 题目大意:给你n个点,n-1条边,然后是m次询问,每一次询问给你u,v,w然后问你从u -> v 的路径上有多少边 ...
- python 列表 元组 字典 集合
列表 lst = [i for i in range(10)] 切片 # 把下标小于2的显示出来 print(lst[:2]) # 把10个数有大到小输出 print(lst[::-1]) # 把下标 ...
- k64 datasheet学习笔记26--Oscillator (OSC)
1.前言 OSC模块是一个晶体振荡器. 该模块使用晶体或谐振器与外部连接,为MCU产生一个参考时钟. 主要为下图红色框住的部分 2.特性和模式 Supports 32 kHz crystals (Lo ...
- Cookie 判断页面是否为第一次打开 包括刷新
$.cookie = function(e, t, n) { if(arguments.length > 1 && (!/Object/.test(Object.prototyp ...
- javascript中事件对象注册与删除
事件对象 注册事件 直接给dom对象设置属性,只能给对象设置一个属性,如果设置多个事件处理函数,则最后的生效: 给html标签设置属性,(若法1和法2同时使用,则法1生效): 事件注册 绑定事件监听函 ...
- 【batch】命令对比两个文件夹下的文件(增删改的对比)
1.分别打印两个目录的结构 TREE D:\SOURCE /A /F >D:\SOURCE.TXT TREE D:\DEST /A /F >D:\DEST.TXT 2.然后使用工具/命令进 ...
- 文本框监听事件blur()的简单使用
场景描述:在做编辑功能的时候,经常要判断编码,或者密码之类的是否已经被使用,以前自己做的时候,经常都是在提交了之后才判断的,到现在,才发现,这样做的用户体验不好,完美一点的做法就是当此文本框失去焦点的 ...
- spring boot 添加拦截器的简单实例(springBoot 2.x版本,添加拦截器,静态资源不可访问解决方法)
spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor 一.HandlerInterceptor HandlerInterceptor是s ...
- 使用Percona Data Recovery Tool for InnoDB恢复数据
运维工作中难免会发生一些误操作,当数据库表被误操作删除需要紧急恢复,或者没有备份时,Percona Data Recovery Tool for InnoDB这个工具也已提供一些便捷的恢复. 当然 ...