Oracle表连接优化思路嵌套查询/哈希连接/排序合并连接等

2024年 4月 19日 38.9k 0

Oracle表连接类型:

一、嵌套查询

嵌套循环的算法:在嵌套循环连接中,有驱动顺序,驱动表返回多少条记录,被驱动表就访问多少次,嵌套循环连接中无须排序。

嵌套循环可以快速返回两表关联的前几条数据,如果SQL中添加了HINT:FIRST_ROWS,在两表关联的时候,优化器更倾向于嵌套循环。

在嵌套循环连接,要特别注意驱动表的顺序,小的结果集先访问,大的结果集后访问,才能保证被驱动表的访问次数降到最低,从而提升性能。当两表使用外连接进行关联,如果执行计划是走嵌套循环,那么这时无法更改驱动表,驱动表将会被固定在主表。

驱嵌套循环被驱动表必须走索引。如果嵌套循环被驱动表的连接列没有包含在索引中,那么被驱动表只能走全表扫描,而且是反复多次全表扫描。当被驱动表很大时,SQL就执行不出结果。

嵌套循环被驱动表走索引只能走INDEX UNIQUE SCAN和INDEX RANGE SCAN。嵌套循环被驱动表不能走TABLE ACCESS FULL,不能走INDEX FULL SCAN,不能走INDEX SKIP SCAN,也不能走INDEX FAST FULL SCAN。

嵌套循环查询HINT用法:/+leading(t1) use_nl(t2)/,其中t1为驱动表,t2为被驱动表

SELECT /+leading(t1) use_nl(t2)/ * FROM T1 INNER JOIN ON T1.ID = T2.ID

嵌套连接没有连接条件限制

1、两表关联走不走NL是看两个表关联之后返回的数据量多少?还是看驱动表返回的数据量多少?

如果两个表是1:N关系,驱动表位1,被驱动表为N并且N很大,这时即使驱动表返回数据量很少,也不能嵌套循环,因为两表关联之后返回的数据量会很多。所以判断两个表关联是否应该走NL应该直接查看两个表关联之后返回的数据量,如果两个表关联之后返回的数据量少(比如少于万行),可以走NL;返回的数据量多(比如大于万行)。应该走HASH连接。

2、大表是否可以当嵌套循环(NL)驱动表?

可以,大表过滤之后返回的数据量很少就可以充当NL驱动表

3、select * from a inner join b on a.id = b.id;如果a有100条数据,b表有100万行数据,a与b是1:N关系,N很低,应该怎么优化SQL?

因为a与b是1:N关系,N很低,可以在b的连接列(ID)上创建索引。让a与b走嵌套循环(a nl b),这样b表会被扫描100次,但是每次扫描走表的时候走的是id列的索引(范围扫描)。如果让a与b进行hash连接,b表会被全表扫描(因为没有过滤条件),需要查询表中的100万数据,而如果让a和b进行嵌套循环,b表只需要查询出表中最多几百行数据(100*N)。一般情况下,一个小表与一个大表关联,可以考虑小表NL大表,大表走连接列索引(如果大表有过滤条件,需要将过滤条件与连接列组合起来创建组合索引),从而避免大表被全表扫描。

当a与b是1:N关系,N非常大(比如几十万),SQL执行不出结果。主要是a与b关联后返回大量数据,因为返回结果集太多,被驱动表走索引,也就是说该SQL可能是被驱动表走索引返回大量数据导致的性能问题。这时就不能走嵌套循环了,只能走HASH连接,于是用HINT:USE_HASH(A,B)。所以一般来说看到SQL中有distinct ,group by ,count,分析函数,一定要走HASH。因为一般有这些语句,它返回的结果集都非常大。

4、DBLINK永远不能作为NL的被驱动表。

二、哈希连接

两表关联返回少量数据应该走嵌套循环,两表关联返回大量数据应该走HASH连接。
HASH连接的算法:两表等值关联,返回大量数据,将较小的表选为驱动表,将驱动表的“SELECT列和JOIN列”读入PGA中的WORK AREA,然后对驱动表的连接列进行hash运算生成hash table,当驱动表的所有数据完全读入PGA中的WORK AREA之后,再读取被驱动表(被驱动表不需要读入PGA中的WORK AREA中),对被驱动表的连接列也进行hash运算,然后到PGA中的WORK AREA去探测hash table,找到数据就关联上,找不到数据就没关联上。

在HASH连接中,有驱动顺序, 驱动表和被驱动表都只会访问0次或者1次

在HASH连接中,无须排序,消耗PGA内存是因为用于建立HASH表,当驱动表太大、PGA不能完全容纳驱动表时,驱动表就会溢出到临时表空间,进而产生磁盘HASH连接,这时候HASH连接性能会严重下降。

嵌套循环每循环一次,会将驱动表连接列传值给被驱动表的连接列,也就是说嵌套循环会进行传值。HASH连接没有传值的过程列在进行HASH连接的时候,被驱动表的连接列会产生HASH值,到PGA中去探测驱动表所生成的hash table。HASH连接的驱动表与被驱动表的连接列都不需要创建索引。

OLAP环境多数SQL都是大规模的ETL,此类SQL返回的结果集很多,SQL执行计划通常以HASH为主,往往要大量消耗PGA,所以OLAP系统PGA设置较大。

在HASH连接 连接要特别注意驱动表的顺序,小的结果集先访问,大的结果集后访问,才能保证被驱动表的访问次数降到最低,从而提升性能。

嵌套循环查询HINT用法:/+leading(t1) use_hash(t2)/,其中t1为驱动表,t2为被驱动表

SELECT /+leading(t1) use_hash(t2)/ * FROM T1 INNER JOIN ON T1.ID = T2.ID。

HASH连接主要用于处理两表等值关联

不支持HASH连接的连接条件:连接条件是 > 、>=和=,

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论