在Oracle SQL语句中,如果from后面有多个表时,表的连接方式是一个很重要的考量。

从Oracle 6开始,优化器就支持下面4种表连接方式:

— 嵌套循环连接(Nested Loop Join)

— 群集连接(Cluster Join)

— 排序合并连接(Sort-Merge Join)

— 笛卡尔连接(Cartesian Join)

在Oracle 7.3中,新增加了哈希连接(Hash Join)。

在Oracle 8中,新增加了索引连接(Index Join)。

在这些表连接的方法中,Nested Loop Join和Hash Join及Sort-Merge Join是比较常见的。

(1)Nested Loop Join

这种场景一般适用于大表和小表的关联,准确来说应该是大的行集与小的行集,一般小表适用为驱动表,对于小表中的匹配记录和大表做关联,此时小表是在外部循环,大表在内部循环,小表中的记录都和大表做一个关联。

SQL> create table t as select *from dba_objects where object_id is not null;

SQL> create table t1 as select *from user_objects where object_id is not null;

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade=>TRUE);

SQL> exec dbms_stats.gather_table_stats(user,'T1',cascade=>TRUE);

SQL> create unique index ind_t on t(object_id);

SQL> create unique index int_t1 on t1(object_id) ;

SQL> select count(*)from t;

COUNT(*)

----------

74552

下面的例子,表t1中的数据较少,表t中的数据多,就以表t1为驱动表,走了全索引扫描查取到t1的数据,然后对于t1中的数据和t做匹配,匹配时走了唯一性扫描。

.select t.object_id,t.object_name,t.object_type,t.status from t,t1 where t.object_id=t1.object_id;

(2)Hash Join

这种场景适用于大表和大表之间的关联。通过Hash算法来做两个表之间的匹配映射。

SQL> create table t as select *from dba_objects where object_id is not null;

SQL> create table t1 as select *from dba_objects where object_id is not null;

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade=>TRUE);

SQL> exec dbms_stats.gather_table_stats(user,'T1',cascade=>TRUE);

SQL> create unique index ind_t on t(object_id);

SQL> create unique index int_t1 on t1(object_id) ;

SQL> select count(*)from t;

COUNT(*)

----------

74552

对于表t1中的记录,都是通过Hash映射来匹配表t中的记录。对于CPU的资源消耗还是相对较多的,因为内部做了大量的计算。从生产环境中的实践来说,Hash Join还是不错的,特别是在和并行结合之后。

select t.object_id,t.object_name,t.object_type,t.status from t,t1 where t.object_id=t1.object_id;

(3)Sort-Merge Join

对于Sort-Merge Join来说,可能略微有些陌生。

在数据库中有一个隐含参数对应,默认是开启的,见下表。

Sort-Merge Join相关参数

因为这种连结方式使用不当会消耗大量的系统资源,在一些生产系统中都选择手动禁用这种连结。

这种连结的运行原理相比Nested Loop Join和Hash Join而言没有驱动表,所以Sort-Merge Join可能会产生大量的随机读。

比如我们有表emp、dept。

查询语句为:

select empno,ename,dname,loc from emp,dept where emp.deptno =dept.deptno

如果采用Sort-Merge Join,就会对emp、dept表进行order by 的操作。

类似下面两个操作:

select empno,ename ,deptno from emp order by deptno;

select deptno,dname,loc from dept order by deptno;

因为排序后的数据都是有序的,然后对两个子结果集根据deptno进行匹配。

选择两端的数据列,根据列的要求筛选数据。

我们先来看一个使用Sort-Merge Join的执行计划,实际中需要用到Sort-Merge Join的场景就是在类似下面形式的查询中

where tab1.column1 between tab2.column2 and tab2.column3

我们可以使用Hint ordered来指定连接方式驱动,或者使用hint use_merge来引导查询走Sort-Merge Join,下面简单模拟一下。

(1)使用Hint ordered,语句如下。

SQL> select /*+ordered*/ empno,ename,dname,loc from emp,dept where emp.deptno between dept.deptno-10 and dept.deptno+10;

语句的执行计划如下:

Predicate Information (identified by operation id):

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

4 - filter("EMP"."DEPTNO"<="DEPT"."DEPTNO"+10)

5 - access(INTERNAL_FUNCTION("EMP"."DEPTNO")>="DEPT"."DEPTNO"-10)

filter(INTERNAL_FUNCTION("EMP"."DEPTNO")>="DEPT"."DEPTNO"-10)

可以看到对emp和dept都做了全表扫描,对数据进行了排序,然后根据deptno对结果集进行了匹配和关联,最后把结果集输出。

(2)使用Hint use_merge来实现相同的效果。

SQL> select /*+use_merge(dept,emp)*/ empno,ename,dname,loc from emp,dept where emp.deptno between dept.deptno-10 and dept.deptno+10;

语句的执行计划如下:

Predicate Information (identified by operation id):

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

4 - filter("EMP"."DEPTNO"<="DEPT"."DEPTNO"+10)

5 - access("EMP"."DEPTNO">="DEPT"."DEPTNO"-10)

filter("EMP"."DEPTNO">="DEPT"."DEPTNO"-10)

合并排序的思路和数据结构中的合并排序算法相似,适合在数据筛选条件有限或者返回结果已经排序的场景中使用。如果本身表中的数据量很大,做Sort-Merge Join就会耗费大量的CPU资源,临时表空间相比来说不是很划算,完全可以通过其他的连接来实现。

oracle 表连接 大表小表_优化必备基础:Oracle中常见的三种表连接方式相关推荐

  1. 机器人送丝软管型号和代码_国产焊接机器人的送丝系统可以三种不同的方式送丝...

    国产焊接机器人的送丝系统可以三种不同的方式送丝. 一种送丝方法是拉丝,其将送丝盘和焊枪分开,以便两者通过送丝软管连接. 另一种是将线盘直接安装在焊炬上. 两者均适用于细丝半自动熔化电极气体保护焊. 焊 ...

  2. 数据库中常见的几种表连接方式

    内连接(Inner Join):仅将两个表中满足连接条件的行组合起来作为结果集 自然连接:只考虑属性相同的元组对: 等值连接:给定条件进行查询 不允许null值 外连接(Outer Join) 左连接 ...

  3. python中常见的三种选择结构_在Python中,实现多分支选择结构的最佳方法是

    在Python中,实现多分支选择结构的最佳方法是 答:if-elif-else 绘制建筑平面图时,被剖切的墙用 线绘制,定位轴线用 线绘制 答:粗实 细点画 智慧职教: 下列关于书写住院病历的叙述不正 ...

  4. JAVA共有几种窗体布局方式_在Java GUI程序开发中常见的三种布局管理器是什么

    答:FlowLayout 流式布局,从左到右,如果到边界就换行再从左到右. BorderLayout 边界布局(默认布局方式),按东西南北中五个方向来布局,默认是中.后设置在同样位置的控件会覆盖之前的 ...

  5. oracle数据库开多线程,学习笔记:Oracle表数据导入 DBA常用单线程插入 多线程插入 sql loader三种表数据导入案例...

    天萃荷净 oracle之数据导入,汇总开发DBA在向表中导入大量数据的案例,如:单线程向数据库中插入数据,多线程向数据表中插入数据,使用sql loader数据表中导入数据案例 1.Oracle数据库 ...

  6. DB2支持的三种表空间SMS、DMS、DMS的自动存储

    文章来源:http://blog.itpub.net/25744374/viewspace-750054/ DB2中,表空间是数据库与这个数据库中存储的表之间的逻辑层.表空间在数据库中创建,表在表空间 ...

  7. post 表单中常见的四种表单请求方式

    //post 表单中常见的四种表单请求方式 typedef enum {     postformURLEncoded,                 /*对应Content-Type: appli ...

  8. oracle入门到大神(备mysql、java基础、javaee必经之路)-任亮-专题视频课程

    oracle入门到大神(备mysql.java基础.javaee必经之路)-19178人已学习 课程介绍         Oracle10g的安装.orcale的基本概念介绍.命令行常用操作.Scot ...

  9. vmware虚拟机重装后本机没虚拟网卡解决方案及虚拟机的三种网络连接方式详解

    vmware虚拟机重装后本机没虚拟网卡解决方案: 卸载虚拟机时,就算删除了安装路径,在设备管理器中删除了网卡,在注册列表项中删除了vmware列表项,重装后一般还是会出现本机网络连接中没有没有虚拟机默 ...

最新文章

  1. “半真半假”DeepFake换脸也能精准识别?阿里安全提出全新检测方法
  2. Fragment 与 Fragment 相互传值
  3. eclipse 关闭时progress information弹框_Spring开发环境搭建(Eclipse)
  4. java.util.hashmap_java.util.HashMap中的无限循环
  5. 今天读了JDK1.8源码,知道了并行迭代器Spliterator
  6. 使用C语言扩展Python(四)
  7. Leetcode--3. 无重复字符的最长子串
  8. golang 学习心得一(开发环境搭建过程中一些坑)
  9. win98 老电脑 文件导出_UGNX利器:轻量化建模,很多人还傻傻的关注电脑配置
  10. docker 删除包含关键字的镜像_Docker 架构及工作原理
  11. Java/Hbase + C云平台架构设计_十项法则
  12. abap 创建出口历程_(发展战略)ABAP历史发展
  13. python应用实例:北京城市地方坐标系向BJ54坐标系的变换程序【测绘地质工作者福利】
  14. zip压缩脚本(linux)
  15. 计算机网络 --- HTTP协议 和 HTTPS
  16. 石家庄联通宽带DNS服务器地址
  17. 华硕笔记本能通用的BIOS型号
  18. apache php 整合,【原创】Apache整合PHP
  19. 初学者学习网页设计用什么软件最好?
  20. 购物商城html源码asp,购物商城 html

热门文章

  1. 解读互联网40年中的10大“杀手”病毒
  2. pyInstaller 参数简介
  3. 区块链 智能合约 简介
  4. linux socket 中的backlog参数介绍
  5. linux chpasswd命令 批量修改用户密码
  6. python3 运算符
  7. linux c编译错误storage class specified for parameter XXX
  8. C语言--指针函数和函数指针
  9. Android 进程间通信 实例分析
  10. (八)OpenStack---M版---双节点搭建---Cinder安装和配置