nested loops join(嵌套循环)  

驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制。

驱动表限制条件有索引,被驱动表连接条件有索引。

hints:use_nl()

merge sort join(排序合并)  

驱动表和被驱动表都是最多访问1次,无驱动顺序,需要排序(SORT_AREA_SIZE),连接条件是<>或like导致无法使用。

在连接条件上建立索引可以消除一张表的排序。

hints:use_merge()

hash join(哈希连接)  

驱动表和被驱动表都是最多访问1次,有驱动顺序,无须排序(HASH_AREA_SIZE但是会消耗内存用于建HASH表),连接条件是<> > < 或like导致无法使用。

索引列在表连接中无特殊要求,与单表情况相同。

hints:use_hash()

实验验证:

1.不同表连接的表访问次数验证

2.不同表连接的驱动顺序区别

3.不同表连接的排序情况分析

4.不同表连接的限制场景对比

5.不同表连接和索引的关系

首先,准备两张表t1,t2,分别初始化随机插入100条和100,000条数据:

drop table t1 cascade constraints purge;

drop table t2 cascade constraints purge;

create table t1( id number not null, n number, contents varchar2(4000) );

create table t2( id number not null, t1_id number not null, n number, contents varchar2(4000) );

execute dbms_random.seed(0);

insert into t1  select rownum, rownum, dbms_random.string('a',50)   from dual   connect by level <= 100   order by dbms_random.random;

commit;  

insert into t2  select rownum, rownum, rownum, dbms_random.string('b',50)  from dual  connect by level <= 100000  order by dbms_random.random;

commit;

select count(1) from t1;

select count(1) from t2;

1.不同表连接的表访问次数验证:

set linesize 1000 pagesize 200
alter session set statistics_level = all;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

1.1 nested loops join:

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id;

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n in(17,19);

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 99999999;

1.2 hash join:

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n in(17,19);

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 99999999;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and 1 = 2;

1.3 merge sort join

select /*+ ordered use_merge(t2) */ * from t1, t2 where t1.id = t2.t1_id; 

2.不同表连接的驱动顺序区别:

2.1 nested loops join

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t2)use_nl(t1) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19; 

2.2 hash join

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t2)use_hash(t1) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19; 

2.3 merge sort join

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t2)use_merge(t1) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

说到不同表连接表的驱动顺序,网上也有一个普遍流行的观点,就是小表作为驱动表。其实通过上面的实验可以发现这样的描述是不准确的。

正确地描述应该是:对于nested loops join和hash join来说,小的结果集先访问,大的结果集后访问(即与表的大小没有关系,与具体sql返回的结果集大小有关);而对于merge sort join 来说,先访问谁效率都是一样的。

3.不同表连接的排序情况分析:

嵌套循环,不排序;

hash连接,消耗内存建立hash表;

排序合并,需要排序。

开发人员需要注意不要取多余的字段参与排序:

select /*+ leading(t2)use_merge(t1) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t2)use_merge(t1) */ t1.id from t1, t2 where t1.id = t2.t1_id and t1.n = 19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

4.不同表连接的限制场景对比:

4.1 hash join不支持<> > < like连接条件

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id <> t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id > t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id < t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id like t2.t1_id and t1.n = 19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

4.2 merge sort join不支持<> like 连接方式

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id <> t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id > t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id < t2.t1_id and t1.n = 19;

select /*+ leading(t1)use_merge(t2) */ * from t1, t2 where t1.id like t2.t1_id and t1.n = 19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

4.3 nested loops join 所有都支持

从上面实验结果来看,不能走hash和merge的表连接条件,都会走nested loops join。

5.不同表连接和索引的关系:

5.1 nested loops join

驱动表的限制条件建立索引,被驱动表的连接条件建立索引。

create index idx_t1_n on t1(n);

create index idx_t2_t1_id on t2(t1_id);

select /*+ leading(t1)use_nl(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

5.2 hash join

select /*+ leading(t1)use_hash(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

select * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

一般查询没有合适索引,Oracle都会选择用hash join的表连接。

5.3 merge sort join

create index idx_t1_id on t1(id);
select /*+ ordered use_merge(t2) */ * from t1, t2 where t1.id = t2.t1_id and t1.n = 19;

Oracle 10g版本,在连接条件建立索引可以消除merge sort join表连接的一张表的排序操作。(虽然在两张表的连接条件都建立了索引,却只能消除一张表的排序操作)

注:本文为《收获,不止Oracle》表连接一章的总结笔记。

SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join的更多相关文章

  1. SQL Tuning 基础概述10 - 体会索引的常见执行计划

    在<SQL Tuning 基础概述05 - Oracle 索引类型及介绍>的1.5小节,提到了几种"索引的常见执行计划": INDEX FULL SCAN:索引的全扫描 ...

  2. SQL Tuning 基础概述10

    在<SQL Tuning 基础概述05 - Oracle 索引类型及介绍>的1.5小节,提到了几种"索引的常见执行计划": INDEX FULL SCAN:索引的全扫描 ...

  3. SQL Tuning 基础概述08 - SQL Tuning Advisor

    SQL调优顾问 SQL Tuning Advisor的使用案例: 1.构建测试表T 2.定义调整任务 3.修改调整任务参数 4.执行调整任务 5.监控调整任务 6.查看调整任务建议 7.删除调整任务 ...

  4. SQL Tuning 基础概述01 - Autotrace的设定

    1.autotrace的设定 SQL> set autotrace Usage: SET AUTOT[RACE] {OFF | ON | TRACE[ONLY]} [EXP[LAIN]] [ST ...

  5. SQL Tuning 基础概述04 - Oracle 表的类型及介绍

    Tables A table describes an entity such as employees. You define a table with a table name, such as ...

  6. SQL Tuning 基础概述09 - SQL Access Advisor

    Oracle官方文档对SQL Access Advisor的描述如下: SQL Access Advisor, which is a tuning tool that provides advice ...

  7. SQL Tuning 基础概述05 - Oracle 索引类型及介绍

    一.B-Tree索引 三大特点:高度较低.存储列值.结构有序 1.1利用索引特性进行优化 外键上建立索引:不但可以提升查询效率,而且可以有效避免锁的竞争(外键所在表delete记录未提交,主键所在表会 ...

  8. SQL Tuning 基础概述07 - SQL Joins

    N多年之前,刚刚接触SQL的时候,就被多表查询中的各种内连接,外连接,左外连接,右外连接等各式各样的连接弄的晕头转向. 更坑的是书上看到的各种表连接还有两种不同的写法, 比如对于表A,表B的查询 1, ...

  9. SQL Tuning 基础概述02 - Explain plan的使用

    1.explain plan的使用 SQL> explain plan for delete from t_jingyu; Explained. SQL> select * from ta ...

随机推荐

  1. 【社工】NodeJS 应用仓库钓鱼

    前言 城堡总是从内部攻破的.再强大的系统,也得通过人来控制.如果将入侵直接从人这个环节发起,那么再坚固的防线,也都成为摆设. 下面分享一个例子,利用应用仓库,渗透到开发人员的系统中. 应用仓库 应用仓 ...

  2. 简单粗暴地理解js原型链--js面向对象编程

    原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧, ...

  3. iOS二维码生成、识别、扫描等

    二维码扫描 前言: 最近的项目中使用到了二维码,二维码这个模块功能也完成:觉得还是有必要总结一下用来做记录.好长时间没有写二维码了都忘记在差不多了,重新拾起来还是挻快的. 二维码使用场景: 生活中有很 ...

  4. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  5. ASP.NET Core应用针对静态文件请求的处理[1]: 以Web的形式发布静态文件

    虽然ASP.NET Core是一款"动态"的Web服务端框架,但是在很多情况下都需要处理针对静态文件的请求,最为常见的就是这对JavaScript脚本文件.CSS样式文件和图片文件 ...

  6. 一篇文章看懂TPCx-BB(大数据基准测试工具)源码

    TPCx-BB是大数据基准测试工具,它通过模拟零售商的30个应用场景,执行30个查询来衡量基于Hadoop的大数据系统的包括硬件和软件的性能.其中一些场景还用到了机器学习算法(聚类.线性回归等).为了 ...

  7. Javascript 代理模式模拟一个文件同步功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. C++随笔:从Hello World 探秘CoreCLR的内部(1)

    紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序. 通过我的寻找,其实是一个名为TryRun的文件出了 ...

  9. C#各种同步方法 lock, Monitor,Mutex, Semaphore, Interlocked, ReaderWriterLock,AutoResetEvent, ManualResetEvent

    看下组织结构: System.Object System.MarshalByRefObject System.Threading.WaitHandle System.Threading.Mutex S ...

  10. Android 扫描条形码(Zxing插件)

    使用Android Studio 一.在build.gradle(Module:app)添加代码  下载,调用插件 1 apply plugin: 'com.android.application' ...