Shrink Datafiles – Adjusting HWM
This below example is derived from “Shrinking datafiles” scripts from asktom.oracle.com
Scenario:-
Lets suppose the datafile size is 100m with autoexted upto maxsize 32gb.
1) Created a table
2) Inserted 50millions of rows with commit
— Data file size extended from 100mb to 20gb.
3) performed so many DML’s
— Data file size extended from 100mb to >20gb.
4) Truncated Table/Dropped Table.
Space will can be used further to use for other objects in datafile. But as per my requirement when i really won’t use that datafile, then what is the use to keep datafile size > 20gb and which is causing much disk usage at OS level? Instead of that check the HWM of datafile, at what minimum size you can resize it?
Script for MAX-Shrink:-
set verify off column file_name format a50 word_wrapped column smallest format 999,990 heading "Smallest|Size|Poss." column currsize format 999,990 heading "Current|Size" column savings format 999,990 heading "Poss.|Savings" break on report compute sum of savings on report column value new_val blksize select value from v$parameter where name = 'db_block_size'; / select file_name, ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) smallest, ceil( blocks*&&blksize/1024/1024) currsize, ceil( blocks*&&blksize/1024/1024) - ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) savings from dba_data_files a, ( select file_id, max(block_id+blocks-1) hwm from dba_extents group by file_id ) b where a.file_id = b.file_id(+) order by savings desc /
In lower versions you can use below query to find out possible savings from each data files of Database.
set linesize 400 col tablespace_name format a15 col file_size format 99999 col file_name format a50 col hwm format 99999 col can_save format 99999 SELECT tablespace_name, file_name, file_size, hwm, file_size-hwm can_save FROM (SELECT /*+ RULE */ ddf.tablespace_name, ddf.file_name file_name, ddf.bytes/1048576 file_size,(ebf.maximum + de.blocks-1)*dbs.db_block_size/1048576 hwm FROM dba_data_files ddf,(SELECT file_id, MAX(block_id) maximum FROM dba_extents GROUP BY file_id) ebf,dba_extents de, (SELECT value db_block_size FROM v$parameter WHERE name='db_block_size') dbs WHERE ddf.file_id = ebf.file_id AND de.file_id = ebf.file_id AND de.block_id = ebf.maximum ORDER BY 1,2);
Sample Output of above query:-
Smallest
Size Current Poss.
FILE_NAME Poss. Size Savings
-------------------------------------------------- -------- -------- --------
/u02/oradata/cpdevdb/cp_jrnl_idx3.dbf 13,697 32,708 19,011
/u02/oradata/cpdevdb/cp_jrnl_idx2.dbf 13,761 32,748 18,987
/u02/oradata/cpdevdb/cp_jrnl_idx1_01.dbf 13,953 32,748 18,795
/u02/oradata/cpdevdb/cp_jrnl_idx1.dbf 13,953 32,728 18,775
/u02/oradata/cpdevdb/cp_jrnl_idx3_02.dbf 15,681 32,738 17,057
/u02/oradata/cpdevdb/cp_jrnl_idx3_03.dbf 15,681 32,718 17,037
/u02/oradata/cpdevdb/psindex_01.dbf 11,285 26,718 15,433
/u02/oradata/cpdevdb/cp_jrnl_idx4.dbf 22,913 32,728 9,815
/u02/oradata/cpdevdb/cpled_2010_1.dbf 7,721 10,858 3,137
/u02/oradata/cpdevdb/cpled_2009_1.dbf 4,745 6,828 2,083
/u02/oradata/cpdevdb/cpled_2008_1.dbf 4,873 6,948 2,075
/u02/oradata/cpdevdb/cpled_2009_2.dbf 4,825 6,728 1,903
/u02/oradata/cpdevdb/cpled_idx_1.dbf 19,905 21,000 1,095
--------
sum 145,203
By the output i can reclaim space around 141gb of space, without reorganizing any objects. 🙂
Resize Datafiles:-
We can resize datafile up to “Smallest Size Poss” value (or) we can assign any fixed size (or) On top of that we can enable autoextend up to maximum size of datafile.
alter database datafile '/u02/oradata/cpdevdb/cp_jrnl_idx3.dbf' resize 13700m; alter database datafile '/u02/oradata/cpdevdb/cp_jrnl_idx3.dbf' autoextend on next 10m maxsize 32767m;
After resizing datafile, Possible savings recorded is around 19GB.
Execute above Script to check changes after resizing of datafiles:-
Smallest
Size Current Poss.
FILE_NAME Poss. Size Savings
-------------------------------------------------- -------- -------- --------
/u02/oradata/cpdevdb/cp_jrnl_idx3.dbf 13,697 13,700 3
/u02/oradata/cpdevdb/cp_jrnl_idx2.dbf 13,761 13,770 9
/u02/oradata/cpdevdb/cp_jrnl_idx1_01.dbf 13,953 13,970 17
/u02/oradata/cpdevdb/cp_jrnl_idx1.dbf 13,953 13,970 17
/u02/oradata/cpdevdb/cp_jrnl_idx3_02.dbf 15,681 15,690 9
/u02/oradata/cpdevdb/cp_jrnl_idx3_03.dbf 15,681 15,690 9
/u02/oradata/cpdevdb/psindex_01.dbf 11,285 11,300 15
/u02/oradata/cpdevdb/cp_jrnl_idx4.dbf 22,913 22,920 7
/u02/oradata/cpdevdb/cpled_2010_1.dbf 7,721 7,730 9
/u02/oradata/cpdevdb/cpled_2009_1.dbf 4,745 4,750 5
/u02/oradata/cpdevdb/cpled_2008_1.dbf 4,873 4,900 27
/u02/oradata/cpdevdb/cpled_2009_2.dbf 4,825 4,850 25
/u02/oradata/cpdevdb/cpled_idx_1.dbf 19,905 19,910 5
--------
sum 157
In earlier output possible savings is 141gb, Now possible savings is 157mb, So we reclaimed ~141gb of space at OS level. 🙂
Now lets compare OS level free space Before & After
Before:-
$df -h /u02
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vgemc4-lvu02
1.5T 1.3T 161G 89% /u02
After:-
$df -h /u02
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vgemc4-lvu02
1.5T 942G 461G 68% /u02
I able to reclaim space by adjusting HWM from two databases around 300GB. Here you go……………
Note:- I have reclaimed for other databases reside on that server, so you can see much differences before and after.