一个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

;

原文地址:https://www.cnblogs.com/wcwen1990/p/9325968.html

时间: 2024-10-07 19:09:53

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

举例一个比较好的表连接的执行计划

SQL> var loc varchar2(30) SQL> exec :loc:='South San Francisco' PL/SQL procedure successfully completed. SQL> SELECT 2 emp.last_name,emp.first_name,j.job_title,d.department_name,l.city,l.state_province,l.postal_code,l.street_address, 3 emp.email,

oracle sql 执行计划分析

转自http://itindex.net/detail/45962-oracle-sql-%E8%AE%A1%E5%88%92 一.首先创建表 SQL> show user USER is "RHYS" SQL> create table A(col1 number(4,0),col2 number(4,0), col4 char(30)); create table B(col1 number(4,0),col3 number(4,0), name_b char(30))

Oracle SQL执行计划基线总结(SQL Plan Baseline)

一.基础概念 Oracle 11g开始,提供了一种新的固定执行计划的方法,即SQL plan baseline,中文名SQL执行计划基线(简称基线),可以认为是OUTLINE(大纲)或者SQL PROFILE的改进版本,基本上它的主要作用可以归纳为如下两个: 1.稳定给定SQL语句的执行计划,防止执行环境或对象统计信息等等因子的改变对SQL语句的执行计划产生影响! 2.减少数据库中出现SQL语句性能退化的概率,理论上不允许一条语句切换到一个比已经执行过的执行计划慢很多的新的执行计划上! 注意:

DB查询分析器7.01新增的周、月SQL执行计划功能

马根峰              (广东联合电子服务股份有限公司, 广州 510300) 1      引言   中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本DB 查询分析器.英文版本<DB Query Analyzer>.它具有强大的功能.友好的操作界面.良好的操作性.跨越各种数据库平台乃至于EXCEL和文本文件. 你可以通过它 ① 查询ODBC数据源(包括世面上所有的数据库.TXT/CSV文件.EXC

总有一种SQL执行计划绑定方式合适你

需要绑定SQL执行计划常见的几种情况: SQL执行计划突变,导致数据库性能下降,从历史执行计划找一个合理的,进行绑定. SQL无法使用更优的执行计划,且无历史执行计划,可通过hint手工构造的方式,进行绑定. 某些Bug引起优化器生成较差的执行计划.在bug修复前,进行绑定. ORACLE固定执行计划的3种方式: Oracle 9i使用outline (可跨版本10,11g均可使用) Oracle 10g使用sql profile (11g也可使用) Oracle 11g使用sql plan m

ASP连接sql server实例解析

1.首先确定自己的iis没有问题 2.其次确定自己sqlserver没有问题 然后在iis的文件夹wwwroot里,建立一个文件 名为testSqlServer.asp,编写代码例如以下就可以 <% 'ole db连接 set cnn1 = Server.CreateObject("ADODB.Connection") '连接串需要注意sqlserver的实例名,是否是默认,非默认必需要写出来 cnn1.Open "provider=sqloledb;data sour

Oracle查看SQL执行计划的方式

Oracle查看SQL执行计划的方式   获取Oracle sql执行计划并查看执行计划,是掌握和判断数据库性能的基本技巧.下面案例介绍了多种查看sql执行计划的方式: 基本有以下几种方式: 1.通过sql_trace初始化参数 2.通过Autotrace 3.通过explain plan 4.通过dbms_xplan.display_cursor 5.通过dbms_xplan.display_awr 6.通过10046事件 1.通过explain plan 工具 12:24:00 [email

plsql中查看sql执行计划

想要优化sql语句,可以从sql执行计划入手. 在plsql客户端,提供了一个方便的按钮来查看执行计划 选中需要查看的sql语句,点击此按钮,就可以看到该条语句的执行计划了. 结果集包括描述,用户,对象,花销等,和功能相同的sql语句比较花销就能看出哪条sql的性能更优.

手动创建SQL_profile 改变和稳定 SQL 执行计划

原来语句执行计划 SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.object_id; --------------------------------------------------------------------------- | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)|