will delete reclaim database free space ?
Raj, March 11, 2001 - 11:15 pm UTC
I was currently at the verge of running a report to see how much space I have I one of my databases. My colleague complained that he deleted about 1 - 2 gig of data and the free space report is still showing the same count. He was wondering how. The answer for the question helped me to explain the situation to him. Very helpful. Thanks.
A reader, September 04, 2002 - 11:56 am UTC
Tom:
Is there anyway to reclaim the space(ie. reset the HWM) after a large delete?
I have inherited a database that had massive deletes. These tables are going to be static now. How can I reclaim some of the space allocated to this database to make room for another. My 'alter database datafile resize' returns data above size error. Is it not due to the HWM still high? Please advice. Thanks.
September 04, 2002 - 3:19 pm UTC
alter table T move;
(and then rebuild the indices on that table)
I would:
o create a new locally managed tablespace with autoextend datafiles (so the files will grow just as big as needed)
o alter table T move tablespace that_new_one
o alter index I rebuild tablespace that_new_one
o drop tablespace that_old_one;
A reader, September 09, 2002 - 11:58 am UTC
I moved the tables and was able to reset the HWM. However, I am still not able to resize the datafiles. Please see the following:
1 select file_name, bytes/1024/1024 file_size, fs.free_spc,
2 ((bytes/1024/1024-fs.free_spc)) diff
3 from dba_data_files df, ( select file_id, sum(bytes)/1024/1024 free_spc
4 from dba_free_space group by file_id ) fs
5 where df.file_id=fs.file_id
6 and df.tablespace_name='MOBIUS'
7* order by df.tablespace_name, 1
SQL> /
FILE_NAME FILE_SIZE FREE_SPC DIFF
--------------------------------------------- ---------- ---------- ----------
/u13/oradata/PPIIMG/mobius01.dbf 2000 1966.40234 33.5976563
/u14/oradata/PPIIMG/mobius02.dbf 2000 1949.11719 50.8828125
/u14/oradata/PPIIMG/mobius10.dbf 1024 989.328125 34.671875
/u15/oradata/PPIIMG/mobius03.dbf 2000 1626.30469 373.695313
/u16/oradata/PPIIMG/mobius04.dbf 2000 1766.30469 233.695313
/u16/oradata/PPIIMG/mobius05.dbf 1200 1160.34766 39.6523438
/u17/oradata/PPIIMG/mobius06.dbf 1200 1160.35156 39.6484375
/u17/oradata/PPIIMG/mobius08.dbf 1024 991.355469 32.6445313
/u18/oradata/PPIIMG/mobius07.dbf 1100 1080.34766 19.6523438
/u18/oradata/PPIIMG/mobius09.dbf 1024 995.34375 28.65625
10 rows selected.
SQL> alter database datafile '/u13/oradata/PPIIMG/mobius01.dbf' resize 200M;
alter database datafile '/u13/oradata/PPIIMG/mobius01.dbf' resize 200M
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
Why can't I resize this datafile to 200M when the only 33 meg of it is used? (as per dba_free_space). What is the mistake I am making? Thanks.
September 09, 2002 - 12:32 pm UTC
search this site for
maxshrink
I have a script that'll generate an alter statement that'll make the files as small as they can go.
You would want to move the files to another tablespace. The high water mark of the files is still "high". You might have 170meg of free space followed by 30meg of used space (and hence the file cannot be shrunk AT ALL).
Moving a table within the same tablespace to reclaim free space
reader, September 09, 2002 - 2:11 pm UTC
Tom,
Instead of moving the table to a new tablespace,
can I move the table to the tablespace that it currently
belongs, ie. doing nothing but just moving it to itself for reclaiming the free space, is it possible ?
September 09, 2002 - 7:43 pm UTC
maybe, maybe not.
If it is an LMT (locally managed tablespace), we tend to move the data to the "front" of the file (meaning, yes, it would work as you intended, allowing you to shrink the file)
If it is a DMT (dictionary m.t.), we tend to move it where ever fet$ (a database table that returns rows in random order) says to go. It could actually end up moving FURTHER out in the file or nearer to the front, it is not possible to say.
After deleting rows, the space still has not been reused
slmak, May 05, 2003 - 3:00 am UTC
I use 8.0.4 database. After deleting a large amount of rows, I suppose that the tablespace will not grow for a period of time, as the space of the deleted rows should be filled by the new inserted rows. But the truth is that the tablespace keeps growing large, and run out of space.
This happens to both the data and index tablespaces. Should I move the table to a new tablespace and also rebuild the index to a new tablespace, so as to reclaim space?
Thanks
May 05, 2003 - 7:42 am UTC
tell us how you "fill" the table. insufficient data to say anything about anything.
RE:After deleting rows, the space still has not been reused
slmak, May 05, 2003 - 9:02 pm UTC
We use Oracle Application. We followed the instructions from Oracle to archive and purge the old data of our inventory system. After purging, we expect this will free enough space for new data. But our inventory tablespace continues to run out of space. I don't know whether the new data use those free space or not.
Thanks in advance.
May 05, 2003 - 9:19 pm UTC
you must contact support for assistance with this. moving applications tables and reorging will need their approval.
if the rows were deleted and the blocks the rows were on caused the row to fall below the pctused setting -- they would be on the freelist and available for reuse.
'delete' and reclaiming of space released - Ver 8.1.7.3
Deepak Bhaskaran, May 06, 2003 - 6:28 pm UTC
Tom,
I appreciate your contribution to the Oracle community which has helped us
get a better understanding of the Oracle database.
reading this thread, i believe i have a similar issue wherein i couldn't see the data blocks being reused,
despite a 'delete' following an 'insert' of 1 rec.
After using block# 48072, it goes on to use block # 48073 and so on.....
If the rows are being deleted immediately, shouldn't block#48072 be the only block
that takes inserts?
show_space does show 3 blocks on the free-list.
Could it be that i'm missing something here?
Loop (for each ee being processed)
insert 1 rec in table <dpk_tmp1>;
process <......>;
delete from table <dpk_tmp1>;
End loop;
-- here is the table definition
CREATE TABLE dpk_tmp1
(
employee_number VARCHAR2(10),
count NUMBER,
jn_date DATE
)
PCTFREE 10
PCTUSED 40
INITRANS 1
MAXTRANS 255
TABLESPACE tmt_tab
STORAGE (
INITIAL 40960
NEXT 40960
PCTINCREASE 50
MINEXTENTS 1
MAXEXTENTS 505
)
Here is the plsql code that I used for the test:
declare
v_blk_no number;
v_row_no number;
begin
dbms_output.put_line('*************************');
dbms_output.put_line('Calling show_space BEFORE');
dbms_output.put_line('*************************');
show_space('DPK_TMP1');
for i in 1..4000 loop
insert into dpk_tmp1 (employee_number, count, jn_date) values ('Emp '||i, i, sysdate);
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid),
dbms_rowid.ROWID_ROW_NUMBER(rowid)
into v_blk_no, v_row_no
from dpk_tmp1
where employee_number = 'Emp '||i;
-- ----------------------------------------------
-- Dump the block# and row# before the delete
-- -----------------------------------------------
insert into dpk_tmp_tab1 (block_no, row_no, employee_number)
values (v_blk_no, v_row_no, 'Emp '||i);
-- --------------------------------------------------------
-- Now, lets delete the inserted rec from dpk_tmp1
-- --------------------------------------------------------
delete from dpk_tmp1;
end loop;
dbms_output.put_line('*************************');
dbms_output.put_line('Calling show_space AFTER');
dbms_output.put_line('*************************');
show_space('DPK_TMP1');
exception
when others then
dbms_output.put_line('Error : '||sqlerrm);
end;
/
And here is the result from running the above plsql code:
MYDB> @1
"truncate table dpk_tmp1
Table truncated.
truncate table dpk_tmp_tab1
Table truncated.
select count(*) from dpk_tmp1
COUNT(*)
----------
0
select block_no, count(*) from dpk_tmp_tab1 group by block_no
no rows selected
Running the plsql code
*************************
Calling show_space BEFORE
*************************
Free Blocks.............................0
Total Blocks............................5
Total Bytes.............................40960
Unused Blocks...........................4
Unused Bytes............................32768
Last Used Ext FileId....................10
Last Used Ext BlockId...................48071
Last Used Block.........................1
*************************
Calling show_space AFTER
*************************
Free Blocks.............................3
Total Blocks............................5
Total Bytes.............................40960
Unused Blocks...........................1
Unused Bytes............................8192
Last Used Ext FileId....................10
Last Used Ext BlockId...................48071
Last Used Block.........................4
PL/SQL procedure successfully completed.
"select block_no, count(*) from dpk_tmp_tab1 group by block_no;"
BLOCK_NO COUNT(*)
---------- ----------
48072 1817
48073 1817
48074 366
*****************BLOCK/EMP/ROW******************
select * from dpk_tmp_tab1 where (block_no, row_no) in
(select block_no, max(row_no) row_no from dpk_tmp_tab1 group by block_no);
BLOCK_NO EMPLOYEE_NU ROW_NO
----------- ---------- ----------
48072 Emp 1817 1816
48073 Emp 3634 1816
48074 Emp 4000 365
thanks
deepak
May 06, 2003 - 6:44 pm UTC
throw a couple of commits in there and see what happens. you have an "atypical" case.
Inventory Tablespace growing even after purge
Logan Palanisamy, May 07, 2003 - 10:19 am UTC
slmak from Hong Kong,
You are saying the Inventory tablespace is growing even after running the purge routines. There could be other tables in the inventory tablespace that are growing contributing to the out of tablespace condition! Are you sure the purged tables are the ones that are growing?
Check the dba_segments and dba_extents tables for the purged table to see whether they are still growing or reusing the deleted space.
'delete' and reclaiming of space
Deepak Bhaskaran, May 07, 2003 - 7:33 pm UTC
thanks tom....it works when i issue a commit.
then again, it appears to be a function of the commit-size.
( I hope i have presented sufficient information for your analysis).
With a commit-size of 1 (ie., if i issue a commit after each delete),
the number of blocks on the freelist stays at 1 (and all records are inserted in block # 48072)
With a commit-size of 1500 and above, however, the number of blocks on the
freelist increases with each subsequent run (and the records are inserted
in multiple blocks.....9 blocks, to be precise)
For each commit-size, this is how i ran the test:
-------------------------------------------------
after choosing a commit-size (say, 2000) , i would run the 1st test with the
"truncate table" in place, and all subsequent runs for the same commit-size will not do the truncate table.
The number of blocks on the freelist stays at 1 upto a commit-size of 1000.
Here's what i mean:
////////////////////////////////////////////////////////////
when COMMIT SIZE = 1000
////////////////////////////////////////////////////////////
at the end of the 4th pass (ie., 4000 * 4 = 16000 records inserted/deleted)
*************************
Calling show_space BEFORE
*************************
Free Blocks.............................1
Total Blocks............................5
Total Bytes.............................40960
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................10
Last Used Ext BlockId...................48071
Last Used Block.........................2
COMMITing, i = 1000
COMMITing, i = 2000
COMMITing, i = 3000
COMMITing, i = 4000
*************************
Calling show_space AFTER
*************************
Free Blocks.............................1
Total Blocks............................5
Total Bytes.............................40960
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................10
Last Used Ext BlockId...................48071
Last Used Block.........................2
PL/SQL procedure successfully completed.
"select block_no, count(*) from dpk_tmp_tab1 group by block_no;"
BLOCK_NO COUNT(*)
---------- ----------
48072 16000
////////////////////////////////////////////////////////////
when COMMIT SIZE = 2000
////////////////////////////////////////////////////////////
at the end of the 4th pass (ie., 4000 * 4 = 16000 records inserted/deleted)
Running the plsql code
*************************
Calling show_space BEFORE
*************************
Free Blocks.............................19
Total Blocks............................20
Total Bytes.............................163840
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................8
Last Used Ext BlockId...................69064
Last Used Block.........................10
COMMITing, i = 2000
COMMITing, i = 4000
*************************
Calling show_space AFTER
*************************
Free Blocks.............................29
Total Blocks............................35
Total Bytes.............................286720
Unused Blocks...........................5
Unused Bytes............................40960
Last Used Ext FileId....................10
Last Used Ext BlockId...................74645
Last Used Block.........................10
(Tom: does this mean the HWM is at block 30 ? )
PL/SQL procedure successfully completed.
"select block_no, count(*) from dpk_tmp_tab1 group by block_no;"
BLOCK_NO COUNT(*)
---------- ----------
48072 1817
48073 2000
48074 2000
48075 2000
69064 2000
69069 2000
74645 2000
74650 183
178361 2000
(ie., the 16K records are spread across multiple blocks)
************** USER_EXTENTS ************
select extent_id, bytes, blocks
from user_extents where segment_name = upper('dpk_tmp1') order by extent_id
EXTENT_ID BYTES BLOCKS
---------- ---------- ----------
0 40960 5
1 40960 5
2 81920 10
3 122880 15
************** USER_EXTENTS ************
thanks
deepak
Partial Delete of a Very Large Table
John Gilmore, November 24, 2003 - 5:17 am UTC
Hi Tom,
We have a table with about 26 million rows and have decided to archive everything older than three months. This means deleting about 21 million rows.
I would expect that a straight "delete" statement would take a considerable amount of time and, as mentioned above, would still not automatically release the disk space allocated to this table.
My current plan is to create a copy of the table in a new tablespace, truncate the old table and then populate it from the copy as required. The new table, together with its tablespace, can then be dropped.
Any thoughts on this approach?
Thanks for your assistance.
November 24, 2003 - 8:20 am UTC
why not:
a) create table NEW as select rows to keep, index it, grant it
b) drop table old
c) rename new to old
and then look at partitioning to permit you to roll data off using DDL in the future.
Null blobs
A reader, October 21, 2004 - 12:25 pm UTC
Hi Tom,
I have a table with a blob column with 10 million rows. I want to set all the blobs to null. This is a permanent update. How do I reclaim the space occupied by the blob column after updating it to null?
Thanks.
October 21, 2004 - 3:00 pm UTC
you would be done, it is "reclaimed", when you start putting blobs back in -- it'll reuse them.
else you can "create table New as select ..."
index it
grant it
whatever it
drop table old;
rename table new to old;
else you can alter table move and move the table/lob after the update to "release" the space for reuse by any other object.
partitioning question
Jerry, November 02, 2004 - 11:54 am UTC
Hi Tom,
You said: "Doing a rolling window is trivial using partitions and aging old data out is a simple DDL operation that takes seconds to perform."
Would it be possible to give an example of how this would be done? I have a large table (> 1Tb) with a LAST_UPDATED column that I'd like to move to a read only tablespace if it is old.
Thanks.
November 03, 2004 - 5:35 am UTC
search for
"rolling window"
on this site.
Is it SQL*Net message from client or db file seq read issue
Moo, May 13, 2005 - 6:43 am UTC
Hi Tom,
Need your advice. WHat is the bottlenect from the following statistics. The query is making use of index for most of the join. Thanks
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 1.20 1.19 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 857 4029.16 4250.58 29940 10368552 0 12830
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 860 4030.36 4251.78 29940 10368552 0 12830
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 858 0.00 0.00
SQL*Net message from client 858 4065.70 4100.49
db file sequential read 29919 0.11 291.78
db file scattered read 5 0.01 0.05
latch free 13 0.00 0.00
SQL*Net more data to client 799 0.00 0.02
********************************************************************************
reclaim physical space -- oracle 9.2.0.6
Baqir Hussain, May 18, 2005 - 1:09 pm UTC
As you said
"When you delete the data from the table -- the blocks will go onto the freelist
for that table (assuming the amount of space on a block that was freed fell
below the pctused). These blocks will be used for subsequent inserts and
updates into this table."
For example, before the delete on PRIMARY a datafile had 1G. And after the delete, PRIMARY will have the same physical size, as you explained above. Question is
1. After the delete in primary database, is it possible to rclaim physical space on the other instance using RMAN to clone a database?
Thanks
May 18, 2005 - 1:17 pm UTC
1) no, rman will do a bit for bit, byte for byte copy of the database -- whitespace and all
you have to "reorg" or rebuild this structure. in 10g, if you are using ASSM (automatic segment space management) you can "shrink" the table.
Reclaim space after Delete
denni50, May 18, 2005 - 4:00 pm UTC
Tom
maybe I'm looking at this to simplistically,,,however if I want to delete
a million rows from table A to reclaim blocks and reset HWM can I not simply
just:
(assuming a delete cascade was used for any child records, disable/enable constraints)
1) delete million rows from table A
2) create table B as select * from table A
3) truncate table A
4) insert into table A select * from table B
5) drop table B
6) rebuild indexes
:~)
May 18, 2005 - 4:53 pm UTC
that is called a "reorg" where I come from.
you take the data out, you put it back in. reorg.
Getting an accurate table size after delete
ht, August 23, 2005 - 3:18 pm UTC
Tom,
How would I get an accurate representation of the size of each table if deleting/truncating the table isn't reflected in dba_extents? I don't have privs to drop the table or move it to another tablespace.
TIA,
ht
SQL*Plus: Release 9.2.0.5.0 - Production on Tue Aug 23 12:02:48 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
conn scott
Connected.
create table test_emp as select * from emp;
Table created.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
.0625
1 row selected.
delete test_emp;
14 rows deleted.
commit;
Commit complete.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
.0625
1 row selected.
drop table test_emp;
Table dropped.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
1 row selected.
August 24, 2005 - 8:43 am UTC
trunating is (if you truncate and release storage)
and I would argue "so is delete", when you delete, the table stays the same size, period. Unless you are in 10g and the tablespace is ASSM and you shrink the table afterwards that is.
delete releases space back to the TABLE itself, it doesn't shrink the table.
truncating a table and deallocating storage doesn't seem to affect size
ht, August 24, 2005 - 12:22 pm UTC
Tom,
I've modified by test script to truncate the table then deallocate. Is this what you were referring to? The table size still doesn't seem to be accurately reflected.
SQL*Plus: Release 9.2.0.5.0 - Production on Wed Aug 24 09:06:55 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
conn scott
Connected.
create table test_emp as select * from emp;
Table created.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
.0625
1 row selected.
truncate table test_emp;
Table truncated.
alter table test_emp deallocate unused;
Table altered.
/*
DOC>delete test_emp;
DOC>commit;
DOC>*/
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
.0625
1 row selected.
alter table test_emp deallocate unused keep 0k;
Table altered.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
.0625
1 row selected.
drop table test_emp;
Table dropped.
select sum(bytes/1024/1024) from user_extents where segment_name='TEST_EMP';
SUM(BYTES/1024/1024)
--------------------
1 row selected.
August 24, 2005 - 6:29 pm UTC
a segment, as this table is, always has AT LEAST one extent, permanent segments do not have "0 extents".
this is very accurate.
9i and assm not reusing space efficiently
A reader, October 19, 2005 - 4:15 am UTC
you said
"When you delete the data from the table -- the blocks will go onto the freelist"
that is true however I am not sure how does Oracle managed pctused and freelists in assm, we have some event tables which holds maximum 300000 rows and deleted everyday using DELETE statement, these tables has however huge sizes, most of them 2GB.
Why in ASSM Oracle cant reuse the spaces efficiently? My only workaround is going back to pctused and freelists?
October 19, 2005 - 7:10 am UTC
ASSM is optimized to provide for high concurrency, at the cost of less efficient use of space than if you micromanage space yourself.
Why are you not truncating?
9i and assm not reusing space efficiently
A reader, October 19, 2005 - 9:33 am UTC
That is the questions I asked the developers. Why not truncate the tables
They say they dont delete 100% of data based some conditions because the tables are constantly inserted by Tibco Middleware 24x7 so if they truncate the table they might lose data.
I suggested them to use manual segment manegement and setting 1 pctfree and 98 pctused since the tables suffers constantly inserts and deletes to use the space efficiently.
October 19, 2005 - 9:50 am UTC
or use partitioning and truncate yesterdays partition.
another shrink question
Simon, November 04, 2005 - 8:02 am UTC
Hi Tom,
Useful article. I have a tablespace that contained tables owned by users which I have dropped (with cascade so the tables, etc. were removed). I ran your maxshrink script but, alas, the HWM is too high for me to resize and shrink the tablespace and so realise the free space.
There are a few hundred tables and indexes left in this tablespace - is the best method really to move each of the tables and rebuild each of the indexes?
Is there a tablespace-level action that I can take instead?
Thanks,
Si
November 04, 2005 - 8:53 am UTC
you can query dba_extents to see what segment is "furthest out", move that (it'll go nearer to the front of the file - definitely releasing last extent) in the same tablespace - shrink - repeat (but you might repeat a lot)
Tricky
Si, November 04, 2005 - 1:05 pm UTC
Thanks for that.
The dba_segments table was difficult to understand even after recourse to the oracle documentation.
I went for moving the tables and indexes to a new tablespace in the end.
However this left me with problems as there are LOBS and LOB indexes.
In particular I could move the table:
ALTER TABLE CREATE$JAVA$LOB$TABLE MOVE new_tablespace
but not rebuild the index:
ALTER INDEX SYS_IL0000042332C00002$$ REBUILD TABLESPACE <new_tablespace>
ERROR at line 1:
ORA-02327: cannot create index on expression with datatype LOB
Metalink Note:130814.1 tells me to use
ALTER TABLE create$java$lob$table MOVE LOB(lob) STORE AS lobsegment (TABLESPACE jpit_users2_ts);
but how does one choose "lobsegment"??
Thanks
Si
November 04, 2005 - 5:34 pm UTC
(dba_EXTENTS - not segments, you wanted to find the last extent in the file... but anyway)
what do you mean "how does one choose lobsegement"??
Si, November 07, 2005 - 11:20 am UTC
lobsegment: in the ALTER TABLE statement, the entry after "STORE TABLE" requires I name the segment to which I move the lob. I'm not sure how I would choose this, or is it just a case of naming?
November 08, 2005 - 9:19 pm UTC
did not follow you. "store table"?
You do not "name the segment to which I move the lob".
can you give an example?
Faced same problem
VaibhavKumar, March 06, 2006 - 5:58 am UTC
Tom Thanx a lot for u'r artical and argument
I had the same problem having 40 million records in the table I wanted to delete the data for every 45days
This article sown me good way with reason
Thanks
Chan Y L, March 24, 2006 - 1:49 am UTC
Dear Tom,
It is really a great post. Thank you very much.
I have one more question want to ask you.
After truncating a table, the extents and blocks of that table will be released, that mean, dba_free_space will show new free space. Then, how about its indexes? if I truncate a table, should I also concern its indexes? Say, do I need to rebuild the indexes of that table so as to release more free space from the indexes?
Thanks
March 24, 2006 - 9:43 am UTC
the truncate of a table (which can keep the storage as well as release it) will truncate the indexes for you as well.
ops$tkyte@ORA10GR2> create table t
2 as
3 select * from all_objects;
Table created.
ops$tkyte@ORA10GR2> create index t_idx on t(object_name,owner,object_type);
Index created.
ops$tkyte@ORA10GR2> select segment_name, blocks
2 from user_segments
3 where segment_name in ('T','T_IDX')
4 /
SEGMENT_NAME BLOCKS
------------------------------ ----------
T 768
T_IDX 384
ops$tkyte@ORA10GR2> truncate table t reuse storage;
Table truncated.
ops$tkyte@ORA10GR2> select segment_name, blocks
2 from user_segments
3 where segment_name in ('T','T_IDX')
4 /
SEGMENT_NAME BLOCKS
------------------------------ ----------
T 768
T_IDX 384
ops$tkyte@ORA10GR2> truncate table t drop storage;
Table truncated.
ops$tkyte@ORA10GR2> select segment_name, blocks
2 from user_segments
3 where segment_name in ('T','T_IDX')
4 /
SEGMENT_NAME BLOCKS
------------------------------ ----------
T 8
T_IDX 8
Truncating a table
Vikram Romeo, May 31, 2006 - 4:55 pm UTC
Hi Tom,
Consider:
create table t (i int);
13:44:50 vasuv00@GRUMPY.WORLD> insert into t select object_id from all_objects;
23455 rows created.
Elapsed: 00:00:52.03
13:45:57 vasuv00@GRUMPY.WORLD> insert into t select * from t;
23455 rows created.
Elapsed: 00:00:00.02
13:46:00 vasuv00@GRUMPY.WORLD> /
46910 rows created.
Elapsed: 00:00:00.03
13:46:01 vasuv00@GRUMPY.WORLD> /
93820 rows created.
Elapsed: 00:00:00.05
13:46:02 vasuv00@GRUMPY.WORLD> /
187640 rows created.
Elapsed: 00:00:02.00
13:46:05 vasuv00@GRUMPY.WORLD> commit;
Commit complete.
Elapsed: 00:00:00.01
13:46:06 vasuv00@GRUMPY.WORLD> select segment_name, blocks, bytes from user_segments where segment_name='T';
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
BYTES
----------
T 640
5242880
Elapsed: 00:00:02.08
13:46:17 vasuv00@GRUMPY.WORLD> delete t;
375280 rows deleted.
Elapsed: 00:00:15.00
13:46:41 vasuv00@GRUMPY.WORLD> commit;
Commit complete.
Elapsed: 00:00:00.00
13:46:46 vasuv00@GRUMPY.WORLD> select segment_name, blocks, bytes from user_segments where segment_name='T';
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
BYTES
----------
T 640
5242880
Elapsed: 00:00:02.06
13:46:50 vasuv00@GRUMPY.WORLD> truncate table t;
Table truncated.
Elapsed: 00:00:00.02
13:46:57 vasuv00@GRUMPY.WORLD> select segment_name, blocks, bytes from user_segments where segment_name='T';
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
BYTES
----------
T 640
5242880
Elapsed: 00:00:02.06
13:47:08 vasuv00@GRUMPY.WORLD> truncate table t drop storage;
Table truncated.
Elapsed: 00:00:00.02
13:47:12 vasuv00@GRUMPY.WORLD> select segment_name, blocks, bytes from user_segments where segment_name='T';
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
BYTES
----------
T 640
5242880
Elapsed: 00:00:02.05
13:47:16 vasuv00@GRUMPY.WORLD> alter table t move;
Table altered.
Elapsed: 00:00:00.01
13:47:22 vasuv00@GRUMPY.WORLD> select segment_name, blocks, bytes from user_segments where segment_name='T';
SEGMENT_NAME BLOCKS
--------------------------------------------------------------------------------- ----------
BYTES
----------
T 128
1048576
Now the question: Why is it that only the alter table move reduced the number of blocks and bytes. Why didnt the truncate table drop storage achieve that?
Thanks for your time in advance ..
Regards,
Vikram Romeo
June 01, 2006 - 9:19 am UTC
insufficient data - it would be all about the tablespace.
Perhaps you are using dictionary managed, or locally managed with system allocated extent sizes.
but, until you tell us all about the tablespace....
(you should look to see how many EXTENTS you had - might have been "one" right...)
Thanks
Vikram Romeo, June 01, 2006 - 12:32 pm UTC
Thanks Tom,
But I guess as of now, I am not even equipped to answer your question. Can you please direct me to the right resource/link from where I could get to know about this?
Does your latest book on Expert one-one-one oracle cover this aspect?
Thanks for your help again ...
Regards,
Vikram
June 01, 2006 - 1:13 pm UTC
"Expert One on One Oracle" is my first book (2001).
Effective Oracle by Design is the only book that really touches on tablespaces in this manner.
You could just "ask your DBA" about the tablespace.
Thanks Tom
Vikram Romeo, June 01, 2006 - 5:38 pm UTC
Thanks Tom,
But I have already ordered your book "Expert Oracle Database Architecture: 9i and 10g Programming Techniques and Solutions" .. will this book cover this topic?
It is still shipping .. on its way :-)
Would feel happy if it does cover this topic ..
Yes , Asking the DBA is there .. but I would also like to learn some of these myself ... so that I dont need to bug the DBA everytime ... Do you feel a developer should know these things? is it absolutely necessary?
Thanks,
Vikram Romeo
June 01, 2006 - 6:22 pm UTC
I cover tablespaces in that book - yes.
Developer should have a good understanding of these things - yes. The book you have ordered is "my version of the concepts guide" - you might read the "real thing" as well (online at otn.oracle.com - the server concepts guide)
Truncate drop storage did not release the space allocated
A reader, August 20, 2006 - 11:09 am UTC
Hi Tom,
I have a partitioned table that I am purging using truncate with the drop storage clause to purge the table and reclaim the space free up by the truncate to the tablespace. The problem is that the truncate drop storage is not returning the free space to the tablespace. Do you know why this is happening?
The tablespace is a locally managed with system allocated extent sizes.
TABLESPACE_NAME : APP_INDEX
BLOCK_SIZE : 8192
INITIAL_EXTENT : 65536
NEXT_EXTENT :
MIN_EXTENTS : 1
MAX_EXTENTS : 2147483645
PCT_INCREASE :
MIN_EXTLEN : 65536
STATUS : ONLINE
CONTENTS : PERMANENT
LOGGING : LOGGING
FORCE_LOGGING : NO
EXTENT_MANAGEMENT : LOCAL
ALLOCATION_TYPE : SYSTEM
PLUGGED_IN : NO
SEGMENT_SPACE_MANAGEMENT : AUTO
DEF_TAB_COMPRESSION : DISABLED
Could you please tell me what I can do to allow the truncate drop storage to return the freed space to the tablespace again.
Thanks for any help on this.
August 20, 2006 - 12:04 pm UTC
"show me"
ops$tkyte%ORA10GR2> CREATE TABLE t
2 (
3 dt date,
4 x int,
5 y char(200)
6 )
7 PARTITION BY RANGE (dt)
8 (
9 PARTITION part1 VALUES LESS THAN (to_date('13-mar-2003','dd-mon-yyyy')) ,
10 PARTITION part2 VALUES LESS THAN (to_date('14-mar-2003','dd-mon-yyyy')) ,
11 PARTITION junk VALUES LESS THAN (MAXVALUE)
12 )
13 /
CREATE TABLE t
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 1
PART2 1
JUNK 1
ops$tkyte%ORA10GR2> insert into t
2 select to_date( '12-mar-2003', 'dd-mon-yyyy' )+mod(rownum,3), rownum, rownum
3 from all_objects;
50064 rows created.
ops$tkyte%ORA10GR2> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 8
PART2 8
JUNK 8
ops$tkyte%ORA10GR2> truncate table t;
Table truncated.
ops$tkyte%ORA10GR2> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 1
PART2 1
JUNK 1
Truncate drop storage did not release the space allocated
A reader, August 21, 2006 - 11:28 am UTC
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
PL/SQL Release 9.2.0.6.0 - Production
CORE 9.2.0.6.0 Production
TNS for Linux: Version 9.2.0.6.0 - Production
NLSRTL Version 9.2.0.6.0 - Production
SQL> CREATE TABLE t
2 ( dt date,
3 x int,
4 y char(200)
5 )
6 PARTITION BY RANGE (dt)
7 (
8 PARTITION part1 VALUES LESS THAN (to_date('13-mar-2003','dd-mon-yyyy')) ,
9 PARTITION part2 VALUES LESS THAN (to_date('14-mar-2003','dd-mon-yyyy')) ,
10 PARTITION junk VALUES LESS THAN (MAXVALUE)
11 )
12 /
Table created.
SQL> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 1
PART2 1
JUNK 1
SQL> insert into t
2 select to_date( '12-mar-2003', 'dd-mon-yyyy' )+mod(rownum,3), rownum, rownum
3 from all_objects;
31010 rows created.
SQL> commit;
Commit complete.
SQL> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 18
PART2 18
JUNK 18
SQL> truncate table t;
Table truncated.
SQL> select partition_name, extents
2 from user_segments
3 where segment_name = 'T';
PARTITION_NAME EXTENTS
------------------------------ ----------
PART1 18
PART2 18
JUNK 18
SQL> exec print_table('select * from dba_segments where segment_name=''T'' ');
OWNER : SCOTT
SEGMENT_NAME : T
PARTITION_NAME : PART1
SEGMENT_TYPE : TABLE PARTITION
TABLESPACE_NAME : APP_INDEX
HEADER_FILE : 26
HEADER_BLOCK : 43059
BYTES : 3145728
BLOCKS : 384
EXTENTS : 18
INITIAL_EXTENT : 65536
NEXT_EXTENT :
MIN_EXTENTS : 1
MAX_EXTENTS : 2147483645
PCT_INCREASE :
FREELISTS :
FREELIST_GROUPS :
RELATIVE_FNO : 26
BUFFER_POOL : DEFAULT
-----------------
OWNER : SCOTT
SEGMENT_NAME : T
PARTITION_NAME : PART2
SEGMENT_TYPE : TABLE PARTITION
TABLESPACE_NAME : APP_INDEX
HEADER_FILE : 26
HEADER_BLOCK : 43067
BYTES : 3145728
BLOCKS : 384
EXTENTS : 18
INITIAL_EXTENT : 65536
NEXT_EXTENT :
MIN_EXTENTS : 1
MAX_EXTENTS : 2147483645
PCT_INCREASE :
FREELISTS :
FREELIST_GROUPS :
RELATIVE_FNO : 26
BUFFER_POOL : DEFAULT
-----------------
OWNER : SCOTT
SEGMENT_NAME : T
PARTITION_NAME : JUNK
SEGMENT_TYPE : TABLE PARTITION
TABLESPACE_NAME : APP_INDEX
HEADER_FILE : 26
HEADER_BLOCK : 43075
BYTES : 3145728
BLOCKS : 384
EXTENTS : 18
INITIAL_EXTENT : 65536
NEXT_EXTENT :
MIN_EXTENTS : 1
MAX_EXTENTS : 2147483645
PCT_INCREASE :
FREELISTS :
FREELIST_GROUPS :
RELATIVE_FNO : 26
BUFFER_POOL : DEFAULT
SQL> exec print_table('select * from dba_tablespaces where tablespace_name=''APP_INDEX'' ');
TABLESPACE_NAME : APP_INDEX
BLOCK_SIZE : 8192
INITIAL_EXTENT : 65536
NEXT_EXTENT :
MIN_EXTENTS : 1
MAX_EXTENTS : 2147483645
PCT_INCREASE :
MIN_EXTLEN : 65536
STATUS : ONLINE
CONTENTS : PERMANENT
LOGGING : LOGGING
FORCE_LOGGING : NO
EXTENT_MANAGEMENT : LOCAL
ALLOCATION_TYPE : SYSTEM
PLUGGED_IN : NO
SEGMENT_SPACE_MANAGEMENT : AUTO
DEF_TAB_COMPRESSION : DISABLED
-----------------
Thanks for any help you can give on this.
RE: Truncate and extents
Mark A. Williams, August 21, 2006 - 7:35 pm UTC
This sounds similar to bug 4142932 - if you have MetaLink, you might want to check that as a possibility.
- Mark
Also...
Mark A. Williams, August 21, 2006 - 7:38 pm UTC
Also, perhaps having a look at user_extents in addition to user_segments might help verify if the two views "match"...
- Mark
Query
ARU, February 14, 2007 - 9:44 pm UTC
Hi Tom,
I am trying to understand the difference between deallocate unused and effect of 'alter table move' in respect to freeing up deleted space.
Please can you explain.
Regards,
Aru.
February 15, 2007 - 11:38 am UTC
one releases free space above the hwm water mark that has never been used (deallocate unused)
the other rebuilds (and typically compacts) the entire segment - used space and all.
create table t ( x char(2000) );
insert into t select 'x' from all_objects;
commit;
you now have about 50,000*2000 bytes of used storage.
delete from t;
commit;
you will have that much used storage
deallocate unused would not touch the used storage
alter table t move would (upon finding no data) not allocate that storage - the table from alter move would likely be smaller than the deallocate unused.
Move table.
RD, February 14, 2007 - 11:29 pm UTC
Hi Tom,
Earlier in the thread you said
'you can query dba_extents to see what segment is "furthest out", move that(it'll go nearer to the
front of the file - definitely releasing last extent) in the same tablespace - shrink - repeat (but
you might repeat a lot)'
For moving the table to front of file do need to go and move it to different tablespace and then back or is there a way to move the table within the same tablespace?
Regards,
RD
Using ALTER TABLE to reclaim LOB Space
Shark_7-11, August 13, 2007 - 8:25 am UTC
Good day Tom,
Is it possible that altering the table could reclaim some space?
eg:
ALTER TABLE [Table_Name] MOVE LOB([Column_Name]) Store
as (TABLESPACE [Table_Space]);
If so, is it possible to alter(move) it to the SAME Tablespace?
P.S.
I'm new to Oracle so excuse my ingorance
August 15, 2007 - 11:02 am UTC
yes, you can obviously rebuild a table (that is what that does, moves the table and the lob) and you can do that into the same tablespace (you'll have two copies of the data for a bit) and then you have to rebuild all indexes on the table
very drastic approach.
Reclaiming the space after delting the rows
Santosh, November 24, 2008 - 4:45 am UTC
Hi Tom,
This is a best article.
I have a once concern regarding this.
I have deleted some millions of records from a table.
But still the table is showing the same space usage as it was before deleting the records.
Version is:10.2.0.4
Please suggest me how do i reclaim the space.
November 24, 2008 - 6:03 pm UTC
read about
alter table t shrink space compact;
alter table t shrink space;
if you are not using ASSM (automatic segment space management) then read about
alter table t move;
alter index i rebuild -- for each index on t
or dbms_redefinition
and then read about partitioning so you never delete millions of rows again.
delete every 7 days
A reader, December 17, 2009 - 8:55 am UTC
Thanks for the above information about the delete. We have an application that have 5 months of data. It started to be filled up from scrach since 5 months.
We decided to delete 4 months of data as a one shot; and then we will delete so that there will be keeping only the last 7 days of data in this application.
What would you suggest for us to do after those delete in order to re-organize those tables and linked indexes?
1) alter table t shrink space compact?
Thanks a lot
December 17, 2009 - 10:44 am UTC
sure, that'll work.
anvesh, March 11, 2010 - 11:48 am UTC
Dear Tom,
I have tablespace with one datafile of size 10M and autoextend on.
I have a table created with the definition
create table test( blob_id number(19) not null, content blob not null)
I inserted a couple of blobs of size 10 MB each. The datafile size has grown to 38MB. I then deleted both the rows and inserted another blob of size 10MB. The size of the datafile now reads 54MB.
1) Why did the datafile almost grew twice the size of the data ?
2) Why has the additional blob that i inserted not use the free space in the datafile ?
March 12, 2010 - 2:26 pm UTC
1) read about pctversion and how lobs are retained. If you like the way I say it, Expert Oracle Database Architecture covers that - else
http://docs.oracle.com/docs/cd/E11882_01/server.112/e10595/undo002.htm#ADMIN11464 we retain lob data just like we retain undo data - or we use your setting of pctversion to retain data. In any case, recently deleted lob data is not available for reuse in general. It has to 'wait' a while.
2) see #1
A reader, April 28, 2010 - 2:37 am UTC
Dear Tom,
You said recently deleted lob data is not available for reuse, atleast for a while. I tried deleting 1GB blobs from my table and tried adding 1GB blobs after a couple of hours.
It still does not use the free space obtained on delete. It just extends the datafile even more.
If i have a bigfile tablespace whose maximum size is like
30000 GB, and pctversion for the blob table is default (10%). Do the blob versions consume 300GB of space at max ?. This is the tablespace and table that i have used for performing the delete.
April 28, 2010 - 8:00 am UTC
if you have pctversion 10%, then 10% of the segment will be reserved for 'undo' - the larger the segment gets, the larger this 10% is.
If your segment is 10gb (or more), and it is 'full' right now, and you remove 1gb - that 1gb is the 10% held in reserve.
You might consider using retention - instead of pctversion. retention is based on a time period - just like undo_retention. In fact, it is based on the same retention period.
A reader, April 29, 2010 - 6:46 am UTC
Thanks a lot for your replies Tom.
But,
1) When i tried inserting blobs with pctversion 0, the datafile size was increasing exactly by the amount of the data inserted. However when the pctversion is set to default 10%, the datafile size was doubling. Doesnt it mean that the blob is already in reserve at the time of insert itself?. If i delete and insert, shouldnt it just use the free space ?. If the deleted blob is also held in reserve, that means that same version of the blob is being held in reserve twice, right ?.
2) If i dont use both pctversion and retention in my LOB column definition, the default is pctversion right ?. I think pctversion will work fine for me. Even if my datafile size has grown to 1000GB and 100GB is being retained because of pctversion. It will be okay, but only when the other 900GB is being used completely.
We already have a production installation where we have specified neither. And now we are receiving complaints of deleted space not being used for adding more data.
Thanks again for your help.
April 29, 2010 - 7:52 am UTC
we still have to version. it will not immediately reuse the space.
you don't use both, you either pctversion or you retention - but not both.
Blob Delete and Insert
A reader, May 07, 2010 - 8:06 am UTC
Hi Tom,
Iam really confused here.
As you said in your earlier replies, i was able to use the deleted space after some time (i tried it the next day). I was happy and tried the exercise again. Alas, iam now unable to use the deleted space at all.
Also, iam not sure whether this should go into some other thread. But, how will oracle scale with multiple users uploading blobs in the database simultaneously ?. If 50 users are uploading 10MB blobs into the database simultaneously, do you think it would have an adverse affect on the speeds. I got speeds that increase non-linearly with some quadratic factor also thrown in. Am I getting the wrong results ?
May 07, 2010 - 8:50 am UTC
if you have resources such that 50 concurrent users inserting is possible, it'll work just fine.
If you have a 2 cpu machine with a single disk - no, it isn't going to be very nice, but then again - nothing would give 50 concurrent users with big things to write.
If you have sufficient resources (hardware), no problem.
... I got speeds that
increase non-linearly with some quadratic factor also thrown in. ...
sounds really fancy. Other than "non-linear", doesn't compute (just some quadratic factor?
If you just mean "it went up like a hockey stick - raised a bit for a while and then curved up really fast, in the shape of a hockey stick", then this is rather normal and to be expected *regardless* of what you are doing. It means you exhausted the capacity of the machine - and it was unable to respond in a reasonable amount of time.
Truncating ar.hz_param_tab table
Avnish, May 14, 2010 - 1:27 am UTC
Hi Tom,
We have a oracle apps 9.2.0.8 DB. The table ar.hz_parma_tab is gone to size of 66GB and its index ar.hz_param_tab_N1 is around 100GB. We raised SR with oracle support and they told us to truncate this table.
It took us more than 10 hours to truncate this table.
But when we do the following, this is done in less than 30 min:
SQL> truncate table ar.hz_param_tab reuse storage;
Table truncated.
Elapsed: 00:22:55.20
SQL> alter index ar.hz_param_tab_N1 rebuild;
Index altered.
Elapsed: 00:01:17.71
SQL> alter table ar.hz_param_tab move;
Table altered.
Elapsed: 00:00:49.66
While rebuilding of index and table the space is reclaimed very quickly but if we try truncating the table with 'drop storage' or 'deallocate storage' clause it takes lots of time and space is released slowly? what is the reason for it?
Does this means that rebuilding the index and the table after truncating using reuse storage the best way to truncate a huge table?
Deleted LOBs
Mike, June 07, 2010 - 2:13 pm UTC
For a table where the LOBs have been defined using RETENTION (default undo_retention of 900 seconds) is there a way to determine how much space is available for re-use after a delete has been run? DBMS_SPACE.SPACE_USAGE shows all of the blocks as being FULL, which I kind of expected, but I can't seem to determine how much space is consumed by LOBS that have been deleted and are 'expired', so to speak, and are therefore available for re-use.
Difference between Deallocating and shrinking
Praveen, January 28, 2011 - 9:54 pm UTC
Hi Tom,
In 10g and up we can shrunk the tablespace using "alter table tt shrink space" (there are restrictions though)
and we can deallocate unused space using "alter table deallocate unused"
how these both are different? Does the second statement have any restrictions such as can't use on the table which function based indexes or so?
thanks
February 01, 2011 - 3:39 pm UTC
shrink space will reorganize the table (moving rows to the "top" of the table) and then redraw the high water mark and then deallocate unused space above the high water mark.
deallocate unused just deallocates unused space above the high water mark.
Using ASM and truncate table to regain space
Carlos, November 21, 2011 - 9:41 am UTC
There is something I do not understand.
We have a similar situation as the one indicated in the message where the user has a 60 GB data nd 100GB index.
Question I have is how this behave when using ASM. It looks that we are not gaing the space from te truncation. Is this due to the usage of ASM that doesn't freed the space? Thank you for your help.
November 21, 2011 - 2:31 pm UTC
ASM doesn't affect this at all.
Tell me how you are measuring things - what are you measuring. Where are you expecting space to be returned?
The truncate - if you have it drop storage, the default - will return space to the freespace for the tablespace.
for example:
ops$tkyte%ORA11GR2> select segment_name, segment_type, blocks
2 from dba_segments where owner = user and segment_name like 'BIG_TABLE%';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
------------------------------ ------------------ ----------
BIG_TABLE TABLE 15360
BIG_TABLE_PK INDEX 2176
ops$tkyte%ORA11GR2> @free 1
%
% MaxPoss Max
Tablespace Name KBytes Used Free Used Largest Kbytes Used
------------------- ------------ ------------ ------------ ------ ------------ ------------ ------
*a ASSM 1,024 64 960 6.3 960 33,554,416 .0
*a EXAMPLE 320,512 310,976 9,536 97.0 8,192 33,554,416 1.0
*a SYSAUX 904,192 810,304 93,888 89.6 30,720 33,554,416 2.7
*a USERS 1,518,336 199,232 1,319,104 13.1 1,013,504 33,554,416 4.5
*m MANUAL 10,240 1,024 9,216 10.0 9,216 33,554,416 .0
*m SYSTEM 887,808 878,080 9,728 98.9 9,216 33,554,416 2.6
*m TMP 512,000 512,000 0 100.0 0 33,554,416 1.5
*m UNDOTBS 3,977,216 38,016 3,939,200 1.0 2,211,840 33,554,416 11.9
------------ ------------ ------------
sum 8,131,328 2,749,696 5,381,632
8 rows selected.
ops$tkyte%ORA11GR2> truncate table big_table;
Table truncated.
ops$tkyte%ORA11GR2> @free 1
%
% MaxPoss Max
Tablespace Name KBytes Used Free Used Largest Kbytes Used
------------------- ------------ ------------ ------------ ------ ------------ ------------ ------
*a ASSM 1,024 64 960 6.3 960 33,554,416 .0
*a EXAMPLE 320,512 310,976 9,536 97.0 8,192 33,554,416 1.0
*a SYSAUX 904,192 810,304 93,888 89.6 30,720 33,554,416 2.7
*a USERS 1,518,336 59,072 1,459,264 3.9 1,153,664 33,554,416 4.5
*m MANUAL 10,240 1,024 9,216 10.0 9,216 33,554,416 .0
*m SYSTEM 887,808 878,080 9,728 98.9 9,216 33,554,416 2.6
*m TMP 512,000 512,000 0 100.0 0 33,554,416 1.5
*m UNDOTBS 3,977,216 38,016 3,939,200 1.0 2,211,840 33,554,416 11.9
------------ ------------ ------------
sum 8,131,328 2,609,536 5,521,792
8 rows selected.
I can see my users tablespace has more free space after the truncate of the table and index...