Tom ,
Segment Advisor does not seem to be giving the accurate space information . Per Example below , the reclaimable space does not match with the space occupied after performing shrink operations.
Please advise , if my understanding is incorrect.
SQL> select sum(bytes)from USER_SEGMENTS where segment_name = 'TCA';
SUM(BYTES)
----------
228589568
SQL> delete from tca;
3606232 rows deleted
SQL> select sum(bytes)from USER_SEGMENTS where segment_name = 'TCA';
SUM(BYTES)
----------
228589568
SQL> commit;
Commit complete
SQL> select sum(bytes)from USER_SEGMENTS where segment_name = 'TCA';
SUM(BYTES)
----------
228589568
Ran the segment advisor from the OEM.
SQL> SELECT allocated_space , used_space , reclaimable_space
2 FROM TABLE(dbms_space.asa_recommendations())
3 Where segment_owner = user
4 and segment_type ='TABLE'
5 and segment_name = 'TCA'
6 /
ALLOCATED_SPACE USED_SPACE RECLAIMABLE_SPACE
--------------- ---------- -----------------
228589568 32917933 195671635
SQL> alter table "TCA" enable row movement;
Table altered
SQL> alter table "TCA" shrink space COMPACT;
Table altered
SQL> alter table "TCA" shrink space;
Table altered
SQL> select sum(bytes)from USER_SEGMENTS where segment_name = 'TCA';
SUM(BYTES)
----------
65536
Everything is an estimate. It is like gathering statistics - we usually use an ESTIMATE. It is like the cardinality in a query plan (explain plan) - it is an estimate.
The segment advisor did a quick sample of that segment and said "hey, this thing is currently large, about 218mb. A quick and dirty sample of the table shows it appears to be mostly empty - we think it would shrink down to be at most about 15% of the current size - it would definitely be a candidate to consider shrinking"
It'll always err on the side of caution, it's job is to find the candidates for shrinking and express a guesstimate of how much space could be saved (if it did the EXACT numbers, it would take so long to complete, it would be useless - you'd have to read the entire database - every byte of it - every time! It is all about samples)
Consider:
ops$tkyte%ORA10GR2> create or replace procedure run_sa
2 authid current_user
3 as
4 obj_id number;
5 begin
6 dbms_advisor.create_task (
7 advisor_name => 'Segment Advisor',
8 task_name => 'Manual_T' );
9
10 dbms_advisor.create_object (
11 task_name => 'Manual_T',
12 object_type => 'TABLE',
13 attr1 => user,
14 attr2 => 'T',
15 attr3 => NULL,
16 attr4 => NULL,
17 attr5 => NULL,
18 object_id => obj_id);
19
20 dbms_advisor.set_task_parameter(
21 task_name => 'Manual_T',
22 parameter => 'recommend_all',
23 value => 'TRUE');
24
25 dbms_advisor.execute_task('Manual_T');
26 end;
27 /
Procedure created.
That'll let us run the advisor from sqlplus whenever...
In the following, we know that the table could be just one extent (64k in my case) - but the sampling is always going to leave room for error - but (seriously) SO WHAT? You have accomplished the goal - "what are the candidate segments for shrinking and what would be a good ball park estimate on what I would save"
ops$tkyte%ORA10GR2> @test 2
ops$tkyte%ORA10GR2> drop table t;
Table dropped.
ops$tkyte%ORA10GR2> create table t
2 as
3 select *
4 from all_objects, (select level l from dual connect by level <= &1)
5 /
old 4: from all_objects, (select level l from dual connect by level <= &1)
new 4: from all_objects, (select level l from dual connect by level <= 2)
Table created.
ops$tkyte%ORA10GR2> select sum(bytes)from USER_SEGMENTS where segment_name = 'T';
SUM(BYTES)
----------
12582912
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> delete from t;
100380 rows deleted.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec run_sa
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> SELECT segment_name,
2 round(allocated_space/1024/1024,1) alloc_mb,
3 round( used_space/1024/1024, 1 ) used_mb,
4 round( reclaimable_space/1024/1024) reclaim_mb,
5 round(reclaimable_space/allocated_space*100,0) pctsave,
6 recommendations
7 FROM TABLE(dbms_space.asa_recommendations())
8 where segment_owner = user
9 /
SEGME ALLOC_MB USED_MB RECLAIM_MB PCTSAVE RECOMMENDATIONS
----- -------- -------- ---------- -------- ----------------------------------------
T 12.0 1.5 11.0 88.0 Enable row movement of the table OPS$TKY
TE.T and perform shrink, estimated savin
gs is 11019016 bytes.
ops$tkyte%ORA10GR2> exec dbms_advisor.delete_task('Manual_T');
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> @test 20
ops$tkyte%ORA10GR2> drop table t;
Table dropped.
ops$tkyte%ORA10GR2> create table t
2 as
3 select *
4 from all_objects, (select level l from dual connect by level <= &1)
5 /
old 4: from all_objects, (select level l from dual connect by level <= &1)
new 4: from all_objects, (select level l from dual connect by level <= 20)
Table created.
ops$tkyte%ORA10GR2> select sum(bytes)from USER_SEGMENTS where segment_name = 'T';
SUM(BYTES)
----------
125829120
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> delete from t;
1003800 rows deleted.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec run_sa
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> SELECT segment_name,
2 round(allocated_space/1024/1024,1) alloc_mb,
3 round( used_space/1024/1024, 1 ) used_mb,
4 round( reclaimable_space/1024/1024) reclaim_mb,
5 round(reclaimable_space/allocated_space*100,0) pctsave,
6 recommendations
7 FROM TABLE(dbms_space.asa_recommendations())
8 where segment_owner = user
9 /
SEGME ALLOC_MB USED_MB RECLAIM_MB PCTSAVE RECOMMENDATIONS
----- -------- -------- ---------- -------- ----------------------------------------
T 120.0 14.9 105.0 88.0 Enable row movement of the table OPS$TKY
TE.T and perform shrink, estimated savin
gs is 110200429 bytes.
ops$tkyte%ORA10GR2> exec dbms_advisor.delete_task('Manual_T');
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> @test 40
ops$tkyte%ORA10GR2> drop table t;
Table dropped.
ops$tkyte%ORA10GR2> create table t
2 as
3 select *
4 from all_objects, (select level l from dual connect by level <= &1)
5 /
old 4: from all_objects, (select level l from dual connect by level <= &1)
new 4: from all_objects, (select level l from dual connect by level <= 40)
Table created.
ops$tkyte%ORA10GR2> select sum(bytes)from USER_SEGMENTS where segment_name = 'T';
SUM(BYTES)
----------
239075328
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> delete from t;
2007600 rows deleted.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec run_sa
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> SELECT segment_name,
2 round(allocated_space/1024/1024,1) alloc_mb,
3 round( used_space/1024/1024, 1 ) used_mb,
4 round( reclaimable_space/1024/1024) reclaim_mb,
5 round(reclaimable_space/allocated_space*100,0) pctsave,
6 recommendations
7 FROM TABLE(dbms_space.asa_recommendations())
8 where segment_owner = user
9 /
SEGME ALLOC_MB USED_MB RECLAIM_MB PCTSAVE RECOMMENDATIONS
----- -------- -------- ---------- -------- ----------------------------------------
T 228.0 29.8 198.0 87.0 Enable row movement of the table OPS$TKY
TE.T and perform shrink, estimated savin
gs is 207840702 bytes.
ops$tkyte%ORA10GR2> exec dbms_advisor.delete_task('Manual_T');
PL/SQL procedure successfully completed.