在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式。多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join.具体适用哪种类型的连接取决于

  • 当前的优化器模式 (ALL_ROWS 和 RULE)
  • 取决于表大小
  • 取决于连接列是否有索引
  • 取决于连接列是否排序

下面来介绍三种不同连接工作方式的不同:

实验sql

假如有10000个城市,对应于10个国家(此例子仅仅可以解释join工作的过程)

更换优化器,添加索引,会影响下面的执行计划。

drop table country;
CREATE TABLE country (
country_id SMALLINT NOT NULL,
country_name VARCHAR(50) NOT NULL
);
drop table city;
CREATE TABLE city (
city_id VARCHAR(50) NOT NULL,
city_name VARCHAR(50) NOT NULL,
country_id SMALLINT NOT NULL
); begin
for i in 1 .. 10 loop
insert into country values(i,'country'||i);
end loop;
commit;
end; begin
for i in 1 .. 10000 loop
insert into city values(i,'city'||i,ceil(i/1000));
end loop;
commit;
end;

一.HASH JOIN:散列连接

Hash join散列连接是CBO 做大数据集连接时的常用方式,优化器使用两个表中较小的表(通常是小一点的那个表或数据源)利用连接键(JOIN KEY)在内存中建立散列表,将列数据存储到hash列表中,然后扫描较大的表,同样对JOIN KEY进行HASH后探测散列表,找出与散列表匹配的行。需要注意的是:如果HASH表太大,无法一次构造在内存中,则分成若干个partition,写入磁盘的temporary segment,则会多一个写的代价,会降低效率。

这种方式适用于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。但是在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要有较大的临时段从而尽量提高I/O 的性能。

可以用USE_HASH(table_name1 table_name2)提示来强制使用散列连接。

使用情况:

Hash join在两个表的数据量差别很大的时候.

二.SORT MERGE JOIN:排序合并连接

Merge Join 是先将关联表的关联列各自做排序,然后从各自的排序表中抽取数据,到另一个排序表中做匹配。

因为merge join需要做更多的排序,所以消耗的资源更多。 通常来讲,能够使用merge join的地方,hash join都可以发挥更好的性能,即散列连接的效果都比排序合并连接要好。然而如果行源已经被排过序,在执行排序合并连接时不需要再排序了,这时排序合并连接的性能会优于散列连接。

可以使用USE_MERGE(table_name1 table_name2)来强制使用排序合并连接.

适用情况:

1.RBO模式

2.不等价关联(>,<,>=,<=,<>)

3.HASH_JOIN_ENABLED=false

4. 用在没有索引,并且数据已经排序的情况.

三.NESTED LOOP:嵌套循环连接

Nested loops 工作方式是循环从一张表中读取数据(驱动表outer table),然后访问另一张表(被查找表 inner table,通常有索引)。驱动表中的每一行与inner表中的相应记录JOIN。类似一个嵌套的循环。

对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择。在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不能太大(大于1 万不适合),要把返回子集较小表的作为外表(CBO 默认外表是驱动表),而且在内表的连接字段上一定要有索引。当然也可以用ORDERED 提示来改变CBO默认的驱动表。

使用USE_NL(table_name1 table_name2)可是强制CBO 执行嵌套循环连接。

适用情况:

适用于驱动表的记录集比较小(<10000)而且inner表需要有有效的访问方法(Index),并且索引选择性较好的时候.

JOIN的顺序很重要,驱动表的记录集一定要小,返回结果集的响应时间是最快的。

参考

三种join方法的理解

多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

Merge join、Hash join、Nested loop join对比分析

nested loop join探讨

多表连接的三种方式详解 hash join、merge join、 nested loop的更多相关文章

  1. 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

    在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...

  2. 多表连接的三种方式 HASH MERGE NESTED

    多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP------------------------------------------------------20 ...

  3. Spring依赖注入三种方式详解

    在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...

  4. React中使用 react-router-dom 路由传参的三种方式详解【含V5.x、V6.x】!!!

    路由传值的三种方式(v5.x) params参数 //路由链接(携带参数): <Link to='/demo/test/tom/18'}>详情</Link> //或 <L ...

  5. springmvc 异常统一处理的三种方式详解

    1 描述  在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦 ...

  6. Mysql 删除数据表的三种方式详解

    用法: 1.当你不再需要该表时, 用 drop; 2.当你仍要保留该表,但要删除所有记录时, 用 truncate; 3.当你要删除部分记录或者有可能会后悔的话, 用 delete. 删除强度:dro ...

  7. mysql备份的三种方式详解

    一.备份的目的 做灾难恢复:对损坏的数据进行恢复和还原需求改变:因需求改变而需要把数据还原到改变以前测试:测试新功能是否可用 二.备份需要考虑的问题 可以容忍丢失多长时间的数据:恢复数据要在多长时间内 ...

  8. 【基于初学者的SSH】struts02 数据封装的三种方式详解

    struts的数据封装共有3中方式,属性封装,模型驱动封装和表达式封装,其中表达式封装为常用 一:属性封装: 属性封装其实就是自己定义变量,注意变量名要和表单的name属性名一致,然后生成get和se ...

  9. 基于JavaScript 声明全局变量的三种方式详解

    原文地址:http://www.jb51.net/article/36548.htm JS中声明全局变量主要分为显式声明或者隐式声明下面分别介绍. 声明方式一: 使用var(关键字)+变量名(标识符) ...

随机推荐

  1. Android之一种很有趣的界面跳动提示动画

    上一个效果图: ==================================== 先上布局: <RelativeLayout xmlns:android="http://sch ...

  2. Android之仿心跳动画实现

    // 按钮模拟心脏跳动 private void playHeartbeatAnimation() { AnimationSet animationSet = new AnimationSet(tru ...

  3. Failed to register: Error: fabric-ca request register failed with errors [[{"code":0,"message":"No identity type provided. Please provide identity type"}]]解决方案

    I try to run sample application as stated here : http://hyperledger-fabric.readthedocs.io/en/release ...

  4. vim去除行显示;vim全部复制命令

    行显示和隐藏: set nu set nu! 直接上命令: ggVG*y 解释一下上面的命令: ggVG   ——全选 *y  —— 复制到剪贴板 gg 是光标定位到文件首行 V  是进入可视模式 G ...

  5. User guide for Netty 4.x

    Table of Contents Preface The Solution Getting Started Before Getting Started Writing a Discard Serv ...

  6. 要恢复页面吗?Chrome未正确关闭

    谷歌chrome浏览器每次打开提示"要恢复页面吗"怎么办? 谷歌chrome浏览器每次打开提示"要恢复页面吗"怎么办? 如下图所示: 每次打开启动谷歌chrom ...

  7. cannot be resolved. It is indirectly referenced from required .class files

    缺少引用. 把缺少的引用在导入一下...如果是mavan 在当前moudle里也要把 dependency加进来

  8. iOS:在cell中使用倒计时的最佳方法

    一.简单介绍 在UITableViewCell中每条数据中显示该内容的倒计时, 并随时间进行倒数,这是很多电商app最常见的活动推销功能模块,自然想到用的就是计时器了. 二.基本想法 想法1:在每个c ...

  9. 聊聊jdbc statement的fetchSize

    在使用MySQL的JDBC时,如果查询结果集过大,使用一次查询,可能会出现Java.lang.OutOfMemoryError: Java heap space问题,因为DB服务器端一次将查询到的结果 ...

  10. Round() 四舍五入 js银行家算法

    首先问一下round(0.825,2) 返回的结果,大家猜一猜, 首先SQL server 返回的是 0.83 js的返回结果 是0.83,code 如下: var b = 0.825;        ...