oracle 11g 新增了一个参数:deferred_segment_creation,含义是段延迟创建,默认是true。具体是什么意思呢?
如果这个参数设置为true,你新建了一个表T1,并且没有向其中插入数据,那么这个表不会立即分配extent,也就是不占数据空间,只有当你insert数据后才分配空间。这样可以节省少量的空间。
一、问题提出:
这带来一个问题:如果你通过EXP命令来导出整个用户时,你会发现所有没有数据的表都导不出来。如何解决这个问题呢?
二、问题分析:
1、既然新建的表没有分配extent,那么在user_segments视图中必然查不到,但是在user_tables中一定是能查到的,这样我们只要找到user_tables中有的,并且user_segments中没有的表,就能找出来哪些表是没有创建extent的。
select *
from user_tables
where table_name not in
(select segment_name from user_segments where segment_type = ‘TABLE‘);
2、找出来后,可以通过alter table xxx allocate extent 语句来让其立即分配extent,这样就可以导出了,例如:
alter table t1 allocate extent (size 64k);
三、问题解决:
1、为了一次性批量把所有这样的“空表”都解决,可以通过批量sql实现:
select ‘alter table ‘ || table_name || ‘ allocate extent(size 64k);‘ sql_text,
table_name,
tablespace_name
from user_tables
where table_name not in
(select segment_name from user_segments where segment_type = ‘TABLE‘);
2、然后把sql_text列在sqlplus中执行一下,就可以通过exp导出了。
3、当然,每次导出都这样做实在是太麻烦了,你完全可以将deferred_segment_creation参数调为false,这样调整后建的表都会立即分配空间,但是调整前的表都不会改变,因此还需要用1、2提到的办法解决。
--调整deferred_segment_creation为false的语法:
conn /as sysdba
alter system set deferred_segment_creation=false;
--如果还想调回来:
conn /as sysdba
alter system reset deferred_segment_creation;
--检查测试数据库:
show parameters deferred_segment_creation;
四、注意事项:
1、现在网上提到的办法都是先往表中间insert 一条数据,然后再rollback,使之分配空间,这种办法比较笨,不推荐。
2、通过move的办法也能得到相同的效果,但也不推荐。