Here's a quick demo to show how specifying STORAGE parameters can affect the actual allocation.
.
.
.
Connected to:So, I have a USERS tablespace with SYSTEM -- i.e. AUTOALLOCATE -- allocation. I have a table with a defined INITIAL of 400MB which got created with 6 Extents of 64MB and 2 Extents of 8MB. What happens if I TRUNCATE the table ?
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> create table A_LARGE_TABLE (col_1 number, col_2 varchar2(5)) storage (initial 400M);
Table created.
SQL> insert into A_LARGE_TABLE values (1,'ABC');
1 row created.
SQL> commit;
Commit complete.
SQL> select bytes/1048576, extents from user_segments where segment_name = 'A_LARGE_TABLE';
BYTES/1048576 EXTENTS
------------- ----------
400 8
SQL> select extent_id, bytes/1024 from user_extents where segment_name = 'A_LARGE_TABLE' order by extent_id;
EXTENT_ID BYTES/1024
---------- ----------
0 65536
1 65536
2 65536
3 65536
4 65536
5 65536
6 8192
7 8192
8 rows selected.
SQL> select tablespace_name, initial_extent , next_extent, pct_increase
2 from user_tables where table_name = 'A_LARGE_TABLE'
3 /
TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT PCT_INCREASE
------------------------------ -------------- ----------- ------------
USERS 419430400 1048576
SQL> select tablespace_name, allocation_type, initial_extent, next_extent
2 from dba_tablespaces where tablespace_name = 'USERS';
TABLESPACE_NAME ALLOCATIO INITIAL_EXTENT NEXT_EXTENT
------------------------------ --------- -------------- -----------
USERS SYSTEM 65536
SQL>
SQL> truncate table A_LARGE_TABLE;*None* of the pre-allocated extents were released ! Oracle doesn't follow the rule "keep the first extent", it follows the rule "keep as many extents as required to satisfy the INITIAL_EXTENT size. What if I rebuild the table with an ALTER TABLE MOVE ?
Table truncated.
SQL> select bytes/1048576, extents from user_segments where segment_name = 'A_LARGE_TABLE';
BYTES/1048576 EXTENTS
------------- ----------
400 8
SQL> select extent_id, bytes/1024 from user_extents where segment_name = 'A_LARGE_TABLE' order by extent_id;
EXTENT_ID BYTES/1024
---------- ----------
0 65536
1 65536
2 65536
3 65536
4 65536
5 65536
6 8192
7 8192
8 rows selected.
SQL>
SQL> alter table A_LARGE_TABLE move;Again, *no difference*. Even the MOVE did not reduce the size of the table. What about a SHRINK ?
Table altered.
SQL> select bytes/1048576, extents from user_segments where segment_name = 'A_LARGE_TABLE';
BYTES/1048576 EXTENTS
------------- ----------
400 8
SQL> select extent_id, bytes/1024 from user_extents where segment_name = 'A_LARGE_TABLE' order by extent_id;
EXTENT_ID BYTES/1024
---------- ----------
0 65536
1 65536
2 65536
3 65536
4 65536
5 65536
6 8192
7 8192
8 rows selected.
SQL>
SQL> alter table A_LARGE_TABLE shrink space;Finally, I am able to shrink the table down. Not to 64KB but to 320KB.
alter table A_LARGE_TABLE shrink space
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled
SQL> alter table A_LARGE_TABLE enable row movement
2 /
Table altered.
SQL> alter table A_LARGE_TABLE shrink space;
Table altered.
SQL> select bytes/1048576, extents from user_segments where segment_name = 'A_LARGE_TABLE';
BYTES/1048576 EXTENTS
------------- ----------
.3125 1
SQL> select extent_id, bytes/1024 from user_extents where segment_name = 'A_LARGE_TABLE' order by extent_id;
EXTENT_ID BYTES/1024
---------- ----------
0 320
SQL>
.
.
.