--并行DDL浅析
以下DDL命令允许并行化:
CREATE INDEX:多个并行执行服务器可以扫描表,对数据排序,并把排序后的段写到索引结构中。
CREATE TABLE AS SELECT:执行SELECT查询可以使用并行查询来执行,而且加载表本身也可以并行完成。
ALTER INDEX REBUILD:索引结构可以并行重建。
ALTER TABLE MOVE:表可以并行移动。
ALTER TABLE SPLIT|COALESCS PARTITION:表分区可以并行的分解或合并。
ALTER INDEX SPLIT PARTITION:索引分区可以并行的分解。
CREATE|ALTER MATERIALIZED VIEW:用并行执行来创建物化视图或修改默认的并行度。
--并行DDL和使用外部表的数据加载
从第五步向下看就是查询部分,big_table的扫描和user_info的散列连接是并行执行的,并将各个子结果加载到表的某个部分中。
以下DDL命令允许并行化:
CREATE INDEX:多个并行执行服务器可以扫描表,对数据排序,并把排序后的段写到索引结构中。
CREATE TABLE AS SELECT:执行SELECT查询可以使用并行查询来执行,而且加载表本身也可以并行完成。
ALTER INDEX REBUILD:索引结构可以并行重建。
ALTER TABLE MOVE:表可以并行移动。
ALTER TABLE SPLIT|COALESCS PARTITION:表分区可以并行的分解或合并。
ALTER INDEX SPLIT PARTITION:索引分区可以并行的分解。
CREATE|ALTER MATERIALIZED VIEW:用并行执行来创建物化视图或修改默认的并行度。
--并行DDL和使用外部表的数据加载
利用并行DDL或并行DML再加上外部表,就能通过一个简单的CREATE TABLE AS SELECT或INSERT /* +APPEND */来实现并行直接路径加载。
例子:
EODA@PROD1> set echo on;
EODA@PROD1>
EODA@PROD1> create table user_info as select * from all_users;
Table created.
EODA@PROD1>
EODA@PROD1> alter table user_info parallel;
Table altered.
EODA@PROD1>
EODA@PROD1> exec dbms_stats.gather_table_stats( user, 'USER_INFO' );
PL/SQL procedure successfully completed.
EODA@PROD1>
EODA@PROD1> create table new_table parallel
2 as
3 select a.*, b.user_id, b.created user_created
4 from big_table a, user_info b
5 where a.owner = b.username;
Table created.
EODA@PROD1>
EODA@PROD1> explain plan for
2 create table new_table parallel
3 as
4 select a.*, b.user_id, b.created user_created
5 from big_table a, user_info b
6 where a.owner = b.username;
Explained.
EODA@PROD1>
EODA@PROD1> select * from table(dbms_xplan.display(null,null,'TYPICAL -COST -ROWS -BYTES'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 3867074464
--------------------------------------------------------------------------------------
| Id | Operation | Name | Time | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------
| 0 | CREATE TABLE STATEMENT | | 00:00:05 | | | |
| 1 | PX COORDINATOR | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 00:00:03 | Q1,01 | P->S | QC (RAND) |
| 3 | LOAD AS SELECT | NEW_TABLE | | Q1,01 | PCWP | |
|* 4 | HASH JOIN | | 00:00:03 | Q1,01 | PCWP | |
| 5 | PX RECEIVE | | 00:00:01 | Q1,01 | PCWP | |
| 6 | PX SEND BROADCAST | :TQ10000 | 00:00:01 | Q1,00 | P->P | BROADCAST |
| 7 | PX BLOCK ITERATOR | | 00:00:01 | Q1,00 | PCWC | |
| 8 | TABLE ACCESS FULL| USER_INFO | 00:00:01 | Q1,00 | PCWP | |
| 9 | PX BLOCK ITERATOR | | 00:00:03 | Q1,01 | PCWC | |
| 10 | TABLE ACCESS FULL | BIG_TABLE | 00:00:03 | Q1,01 | PCWP | |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("A"."OWNER"="B"."USERNAME")
22 rows selected.
从第五步向下看就是查询部分,big_table的扫描和user_info的散列连接是并行执行的,并将各个子结果加载到表的某个部分中。
--参考来源《Oracle编程艺术深入理解数据库体系结构(第三版)》