PDML对空间的浪费

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必须根据系统来选择.

随机日志

Tags:

Leave a Reply