现有如下 SQL。
select * from a,b where a.object_id=b.object_id;
表 a 有 30MB,表 b 有 30GB,两表关联后返回大量数据,应该走 HASH 连接,因为 a 是小表所以 a 应该作为 HASH JOIN 的驱动表,大表 b 作为 HASH JOIN 的被驱动表。在进行 HASH JOIN 的时候,驱动表会被放到 PGA 中,这里,因为驱动表 a 只有 30MB,PGA 能够完全容纳下驱动表。因为被驱动表 b 特别大,想要加快 SQL 查询速度,必须开启并行查询。超大表与超小表在进行并行 HASH 连接的时候,可以将小表(驱动表)广播到所有的查询进程,然后对大表进行并行随机扫描,每个查询进程查询部分 b 表数据,然后再进行关联。假设对以上 SQL 启用 6 个并行进程对 a 表的并行广播,对 b 表进行随机并行扫描(每部分记为 b1,b2,b3,b4,b5,b6)其实就相当于将以上 SQL 内部等价改写为下面 SQL。
select * from a,b1 where a.object_id=b1.object_id ---并行进行
union all
select * from a,b2 where a.object_id=b2.object_id ---并行进行
union all
select * from a,b3 where a.object_id=b3.object_id ---并行进行
union all
select * from a,b4 where a.object_id=b4.object_id ---并行进行
union all
select * from a,b5 where a.object_id=b5.object_id ---并行进行
union all
select * from a,b6 where a.object_id=b6.object_id; ---并行进行
怎么才能让 a 表进行广播呢?我们需要添加hint:**pq_distribute(驱动表 none,broadcast)**
。
现在我们来查看 a 表并行广播的执行计划(为了方便排版,执行计划中省略了部分数据)。
explain plan for select
/*+ parallel(6) use_hash(a,b) pq_distribute(a none,broadcast) */
*
from a, b
where a.object_id = b.object_id;
Explained.
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
Plan hash value: 3536517442
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5064K| 1999M| | |
| 1 | PX COORDINATOR | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 5064K| 1999M| P->S | QC (RAND) |
|* 3 | HASH JOIN | | 5064K| 1999M| PCWP | |
| 4 | PX RECEIVE | | 74893 | 14M| PCWP | |
| 5 | PX SEND BROADCAST | :TQ10000 | 74893 | 14M| P->P | BROADCAST |
| 6 | PX BLOCK ITERATOR | | 74893 | 14M| PCWC | |
| 7 | TABLE ACCESS FULL| A | 74893 | 14M| PCWP | |
| 8 | PX BLOCK ITERATOR | | 5064K| 999M| PCWC | |
| 9 | TABLE ACCESS FULL | B | 5064K| 999M| PCWP | |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("A"."OBJECT_ID"="B"."OBJECT_ID")
如果小表进行了广播,执行计划 Operation 会出现 PX SEND BROADCAST 关键字,PQ Distrib 会出现 BROADCAST 关键字。注意:如果是两个大表关联,千万不能让大表广播。