PDML是一个昂贵的东西,节省了时间但浪费了存储空间,根据不同的情况需要平衡一下, 下面通过一个例子说明:
测试只涉及LMT的情况
非PDML insert:
SQL> create table t3(id number(6),name varchar2(30)) pctfree 10 initrans 1 tablespace mayp;
Table created.
SQL> insert into t3 select * from t1 where rownum<2100000;
2099999 rows created.
SQL> commit;
Commit complete.
PDML insert:
SQL> create table t4(id number(6),name varchar2(30)) pctfree 10 initrans 1 tablespace mayp;
Table created.
SQL> set timing on
SQL> alter table t4 parallel 4;
Table altered.
SQL> alter session enable parallel dml;
Session altered.
SQL> insert into t4 select /*+ parallel(t4,4) */ * from t1 where rownum < 2100000;
2099999 rows created.
SQL> commit;
Commit complete.
观察空间使用:
SQL> exec show_space(‘T3′,’MAYP’);
Unformatted Blocks ………………… 0
FS1 Blocks (0-25) ………………… 3
FS2 Blocks (25-50) ………………… 0
FS3 Blocks (50-75) ………………… 0
FS4 Blocks (75-100)………………… 9
Full Blocks ………………… 6,222
Total Blocks………………………. 6,400
Total Bytes……………………….. 52,428,800
Total MBytes………………………. 50
Unused Blocks……………………… 64
Unused Bytes………………………. 524,288
Last Used Ext FileId……………….. 16
Last Used Ext BlockId………………. 2,057
SQL> exec show_space(‘T4′,’MAYP’);
Unformatted Blocks ………………… 0
FS1 Blocks (0-25) ………………… 0
FS2 Blocks (25-50) ………………… 0
FS3 Blocks (50-75) ………………… 0
FS4 Blocks (75-100)………………… 412
Full Blocks ………………… 6,252
Total Blocks………………………. 6,784
Total Bytes……………………….. 55,574,528
Total MBytes………………………. 53
Unused Blocks……………………… 0
Unused Bytes………………………. 0
Last Used Ext FileId……………….. 16
Last Used Ext BlockId………………. 4,745
Last Used Block……………………. 128
PL/SQL procedure successfully completed.
通过extents观察
SQL> select extent_id,block_id,blocks from dba_extents where segment_name=’T3′;
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
0 9 128
1 12553 128
2 9097 128
3 9 128
4 137 128
5 9225 128
6 137 128
7 265 128
8 9353 128
9 265 128
10 393 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
11 9481 128
12 393 128
13 521 128
14 9609 128
15 521 128
16 649 128
17 9737 128
18 649 128
19 777 128
20 9865 128
21 777 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
22 905 128
23 9993 128
24 905 128
25 1033 128
26 10121 128
27 1033 128
28 1161 128
29 10249 128
30 1161 128
31 1289 128
32 10377 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
33 1289 128
34 1417 128
35 10505 128
36 1417 128
37 1545 128
38 10633 128
39 1545 128
40 1673 128
41 10761 128
42 1673 128
43 1801 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
44 10889 128
45 1801 128
46 1929 128
47 11017 128
48 1929 128
49 2057 128
50 rows selected.
SQL> select extent_id,block_id,blocks from dba_extents where segment_name=’T4′;
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
0 2185 128
1 2313 128
2 11401 128
3 2313 128
4 2825 128
5 11913 128
6 2825 128
7 3337 128
8 12553 128
9 3465 128
10 3977 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
11 3977 128
12 4489 128
13 4489 128
14 2441 128
15 11529 128
16 2441 128
17 2953 128
18 12041 128
19 2953 128
20 3465 128
21 12425 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ——
—-
22 3337 128
23 3849 128
24 3849 128
25 4361 128
26 4361 128
27 11145 128
28 2057 128
29 2697 128
30 11657 128
31 2569 128
32 3081 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
33 12169 128
34 3081 128
35 3593 128
36 3593 128
37 4105 128
38 4105 128
39 4617 128
40 11273 128
41 2185 128
42 2569 128
43 11785 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
44 2697 128
45 3209 128
46 12297 128
47 3209 128
48 3721 128
49 3721 128
50 4233 128
51 4233 128
52 4745 128
53 rows selected.
可以看出pdml比sdml多使用了三个区间.
这中情况是由于在PDML的过程中,每个并行进程会单独各自产生一个extent, 然后insert到各自的extent中, 如果一个exent满了之后,会自动扩展另外一个区间,而且每个进程不会使用其他进程使用的区间,每个进程最后使用的一个区间可能没有完全插满,那么这及个区间就成了比串行插入多出的乃几个区间了.而串行插入是一个一个区间分配的,所以不会造成这种情况.通过简单的表move可以看出这两次插入的数据大小是一致的.
SQL> alter table t4 move tablespace mayp;
Table altered.
SQL> exec show_space(‘T4′,’MAYP’)
Unformatted Blocks ………………… 0
FS1 Blocks (0-25) ………………… 0
FS2 Blocks (25-50) ………………… 0
FS3 Blocks (50-75) ………………… 0
FS4 Blocks (75-100)………………… 0
Full Blocks ………………… 6,250
Total Blocks………………………. 6,400
Total Bytes……………………….. 52,428,800
Total MBytes………………………. 50
Unused Blocks……………………… 48
Unused Bytes………………………. 393,216
Last Used Ext FileId……………….. 15
Last Used Ext BlockId………………. 7,689
Last Used Block……………………. 80
PL/SQL procedure successfully completed.
SQL> select extent_id,block_id,blocks from dba_extents where segment_name=’T4′;
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
0 4873 128
1 4617 128
2 5001 128
3 4745 128
4 5129 128
5 4873 128
6 5257 128
7 5001 128
8 5385 128
9 5129 128
10 5513 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
11 5257 128
12 5641 128
13 5385 128
14 5769 128
15 5513 128
16 5897 128
17 5641 128
18 6025 128
19 5769 128
20 6153 128
21 5897 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
22 6281 128
23 6025 128
24 6409 128
25 6153 128
26 6537 128
27 6281 128
28 6665 128
29 6409 128
30 6793 128
31 6537 128
32 6921 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
33 6665 128
34 7049 128
35 6793 128
36 7177 128
37 6921 128
38 7305 128
39 7049 128
40 7433 128
41 7177 128
42 7561 128
43 7305 128
EXTENT_ID BLOCK_ID BLOCKS
———- ———- ———-
44 7689 128
45 7433 128
46 7817 128
47 7561 128
48 7945 128
49 7689 128
50 rows selected.
move table t4后,可以看出extent被重新分配了, 两个表的大小一样了,因为我的区间分配是extent management local uniform size 1M的标准,如果采用extent management local autoallocate的话,空间浪费可能会小一些.autoallocate的分配模式在并行情况下,具有区间截断功能,也就是说并行进程使用的最后一个区间oracle会根据数据的大小来分配一个小的区间,不会想uniform size一样,每次区间的大小都是一样的.该采用uniform还是autoallocate必须根据系统来选择. 
