oracle表链接的优化

多表链接的三种方式: HASH JOIN,MERGE JOIN,NESTED LOOPhtml

NESTED LOOP: 嵌套循环链接,适用于内表数据量较小时。外表返回的每一行都要在内表中检索找到与它匹配的行,所以整个查询返回的结果集不能太大(大于1 万不适合),并且在内表的链接字段上最好创建索引。sql

HASH JOIN: 哈希/散列链接,适用于小表(驱动表)连大表,且较小的表彻底能够放于内存中的状况。可是在表很大的状况下并不能彻底放入内存,这时优化器会将它分割成若干不一样的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要有较大的临时段从而尽可能提升I/O 的性能。架构

SORT MERGE JOIN: 排序合并链接,适用于没有索引且数据已经排序、不等价关联等状况一般状况下散列链接的效果都比排序合并链接要好,然而若是行源已经被排过序,在执行排序合并链接时不须要再排序了,这时排序合并链接的性能会优于散列链接。oracle

1、 大表关联的优化方法 -- hash分区app

参考连接:20亿与20亿表关联优化方法(超级大表与超级大表join优化方法)函数

问题:两个20亿大表关联耗时一天一晚上post

执行的SQL: select * from t1,t2 where t1.object_id=t2.object_id;性能

关联慢的缘由:单个进程的PGA装不下大表数据 --> 消耗大量临时表空间 --> 临时表来回读写优化

优化方法:url

1)开并行,并行hash。 -- 不可行

2)利用MPP架构/HADOOP架构思想:数据分割。

数据分割方法:一个是分区;另一个是分表。本文选用分区。

步骤:

1)建立表P1,P2。在T1的表结构基础上多加一个字段HASH_VALUE,并且依据HASH_VALUE进行LIST分区。同理,P2。

注意:工做中具体须要多少分区需本身判断,但P1和P2表的分区必须如出一辙。 

CREATE TABLE P1(
HASH_VALUE NUMBER,
OWNER VARCHAR2(30),
OBJECT_NAME VARCHAR2(128),
SUBOBJECT_NAME VARCHAR2(30), 
OBJECT_ID NUMBER,
DATA_OBJECT_ID NUMBER,
OBJECT_TYPE VARCHAR2(19),
CREATED DATE,
LAST_DDL_TIME DATE,
TIMESTAMP VARCHAR2(19),
STATUS VARCHAR2(7),
TEMPORARY VARCHAR2(1),
GENERATED VARCHAR2(1),
SECONDARY VARCHAR2(1),
NAMESPACE NUMBER,
EDITION_NAME VARCHAR2(30)
)   
   PARTITION BY  list(HASH_VALUE)
(
partition p0 values (0),
partition p1 values (1),
partition p2 values (2),
partition p3 values (3),
partition p4 values (4)
)

 2)向P1,P2中插入数据。

oracle中的hash分区就是利用的ora_hash函数。

partition by hash(object_id)  <=> ora_hash(object_id,4294967295)

ora_hash(列,hash桶) ,hash桶默认是4294967295,可以设置0到4294967295。

ora_hash(object_id,4) 会把object_id的值进行hash运算,而后放到 0,1,2,3,4 这些桶里面。

delete t1 where object_id is null;
commit;

delete t2 where object_id is null;
commit;

insert into p1
select ora_hash(object_id,4), a.*  from t1 a;  ---工做中用append parallel并行插入
commit;

insert into p2
select ora_hash(object_id,4), a.*  from t2 a;  ---工做中用append parallel并行插入
commit;

3)执行表关联。

优化后执行时间大约1小时。可将该过程整理为存储过程。

select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=0 and p2.hash_value=0;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=1 and p2.hash_value=1;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=2 and p2.hash_value=2;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=3 and p2.hash_value=3;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=4 and p2.hash_value=4;

 

 2、小表与大表关联 -- hash join

参考连接:oracle表链接----->哈希链接(Hash Join)

对Hash Join的一次优化

1)执行hash join

select /*+ leading(t1) use_hash(t2)*/ * from t1,t2 where t1.id=t2.t1_id;  --可连个表都创建hash,  use_hash(t1 t2)

2)查看执行计划

若是条件成立,驱动表和被驱动表都只被访问1次(主要看 starts),不然访问0次。

哈希链接中驱动表的选择很是重要,性能(主要看 A-Time  | Buffers |  OMem |  1Mem | Used-Mem)差异也大。通常选用结果集较小的表(非数据量)为驱动表

-- 查看执行代码的 sql_id
select sql_id, child_number, sql_text from v$sql where sql_text like '%use_hash(t2)%';

-- 查看指定 sql_id 的执行计划
select * from table(dbms_xplan.display_cursor('036fyatp73h9n',0,'allstats last'));

3)其余

hash join 不支持不等值链接。(执行计划走的是 NESTED LOOPS JOIN)

explain plan for select /*+ leading(t2) use_hash(t1)*/ * from t1,t2 where t1.id<>t2.t1_id and t1.num=20;

select * from table(dbms_xplan.display);

  

  参考连接:

https://zhidao.baidu.com/question/453003972.html

相关文章
相关标签/搜索