4、Truncate drop all storage行为
在11gR2中,Oracle有一个新特性就是deferred_segment_creation参数的引用。在之前的版本中,一旦创建数据表create语句执行,如果初始数据表中没有数据,Oracle是不会创建segment结构,直到第一行数据被插入到数据表中。
这个新特性其实就开启了段结构虚拟化的开端,drop all storage就是将原来保留的一个extent删除掉。
首先将数据插入:
SQL> insert into t select * from dba_objects;
99693 rows inserted
SQL> commit;
Commit complete
段结构如下:
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='T' and owner='TEST';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428808655368
1428816655368
2428824655368
(篇幅原因,有省略……)
264307201048576128
27 rows selected
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='IDX_T_ID' and owner='TEST';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428936655368
1428840655368
2428904655368
(篇幅原因,有省略……)
174302081048576128
18 rows selected
删除段结构。
SQL>truncate table t drop all storage;
Table truncated
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='T' and owner='TEST';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='IDX_T_ID' and owner='TEST';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
虽然没有段结构,但是新的data_object_id编号已经分配了。
SQL> select object_name, object_id, data_object_id from dba_objects where owner='TEST' and object_name in ('T','IDX_T_ID');
OBJECT_NAMEOBJECT_ID DATA_OBJECT_ID
--------------- ---------- --------------
IDX_T_ID123667123672
T123666123673
新段结构虽然没有分配,但是新的编号已经分配。
5、sys用户下的drop all storage
有一点一定注意:drop all storage特性只有在非sys用户下才能使用。如果在sys中使用,drop all storage就和drop storage行为相同。
SQL> show user
User is "SYS"
SQL> create table t tablespace users as select * from dba_objects;
Table created
SQL> create index idx_t_id on t(object_id) tablespace users;
Index created
段结构如下:
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='IDX_T_ID' and owner='SYS';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428936655368
1428944655368
(篇幅原因,有省略……)
15430464655368
164305921048576128
17 rows selected
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='T' and owner='SYS';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428808655368
1428816655368
2428824655368
(篇幅原因,有省略……)
264303361048576128
27 rows selected
执行truncate table操作。
SQL> truncate table t drop all storage;
Table truncated
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='T' and owner='SYS';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428808655368
SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where segment_name='IDX_T_ID' and owner='SYS';
EXTENT_IDFILE_IDBLOCK_IDBYTESBLOCKS
---------- ---------- ---------- ---------- ----------
0428936655368
虽然使用了drop all storage,但是头分区extent结构依然存在。
6、结论
Truncate系列参数给我们提供了控制行为的各种开关。那么我们如何选择呢?笔者认为:不同的业务操作场景,可以使用不同的truncate开关。一般的业务场景下,使用truncate table就是可以的。对于一些经常使用灌入数据的数据表,我们可以预见到过一段时间会有大规模数据insert进入(非append),我们就可以选择reuse storage,这样可以避免下次的频繁空间分配。毕竟空间分配也要消耗资源和时间。对于新特性drop all storage,笔者个人觉得比较鸡肋,在存储日趋便宜的情况下,意义不是很大。