You are on page 1of 4

Managing Fragmentation and Table Shrink in Oracle Database

By Liron Amitzi, Oracle Ace

Introduction
Fragmentation is a common issue which we try to avoid whenever possible. It can
appear in many ways and components and can cause all kind of problems. In this a
rticle I will discuss tablespace fragmentation, which causes a waste of space. T
here can be many causes of tablespace fragmentation, however, I never thought th
at a frequent shrink table command would cause such a fragmentation so quickly.
The Table Shrink Command
Until Oracle 10gR1, when the High Water Mark (HWM) of the table moved forward (a
s new rows were inserted into the table), it could not be moved backwards in ord
er to decrease the table size and de-allocate space, releasing it back to the ta
blespace free space. When we deleted many rows from the table, the HWM and the t
able size remained and the only way to decrease its size was by truncating the t
able. In 10gR1, Oracle introduced an exciting feature called shrink table.
How does it work? When we perform the shrink command, Oracle uses row movement (
which must be enabled on the table) to move rows from the last blocks of the tab
le to the beginning of the table. After moving the rows, a table lock takes plac
e while Oracle moves the HWM backwards. Then, the blocks after the HWM can be re
leased and the table size is reduced.
As you can see below, in normal operation, a table has used blocks (the blue one)
and empty blocks (the orange ones). When rows are inserted into table and there is
no space in the used block, Oracle moves the HWM (the black line) towards the end
of the table, marking the empty blocks as used. Once there are no free blocks left,
another extent is allocated.
frag-image1-jpg

Now lets see how shrink table works. In the diagram below we see that the HWM is
at the end of the table. Assuming we deleted many rows, there are now many place
s in the table blocks to contain new rows. The shrink table command will move th
e rows from the end of the table into free places closer to the beginning of the
table (first drawing). Then, Oracle can move the HWM to the last row of the tab
le, which is now not at the end of the table (second drawing). Once the HWM has
been moved, the blocks beyond it are considered as free blocks (third drawing) a
nd can then be released from the table back to the tablespace (last drawing)
frag-image2-jpg
Locally Managed Tablespaces
The shrink table command works only for segments located in a locally managed ta
blespace with automatic segment space management.
When working with locally managed tablespaces, we have two ways to configure ext
ent allocation:
System allocation - Oracle decides on the extent sizes, regardless of any user c
onfiguration. The segments start with small extents and as they grow, Oracle all
ocates larger and larger extents.
Uniform size - all extents in the tablespace are of the same size, configured wh
en the tablespace was created.
Lets see how system allocation works:
frag-code1-jpg
The above query will show the extents and their size. In my case it returns 202
rows, so Ill sum it up: The first 16 extents were the size of 64KB (8 blocks of 8
KB in my database). The next 63 extents were the size of 1MB. The next 120 exten
ts were the size of 8MB. The three left are 64MB. The idea is quite simple to un
derstand.
How Much Space Does Shrink Table Release?
We saw the idea of shrink table and we understand that it is a very useful comma
nd. Now well try to understand how much space is released back to the tablespace.
In order to do this, we will perform the following:
1.Create two tablespaces, one (tbs_uni) will use uniform extent allocation of 1M
B, the other one (tbs_sys) will use system extent allocation.
2.Create a table in each tablespace (with the same structure and data).
3.Enable row movement for both tables.
4.Check the extents of the tables.
5.Delete rows from both tables.
6.Shrink both tables.
7.Check the extents of the tables to see the released space.

frag-code2-jpg

frag-code3-jpg
Now we will use the query we used before to get the extent allocation:

frag-code4-jpg
Like before, I wont post the entire output here, just the summary:
For table TAB_UNI, which is located in a uniform allocation tablespace, we see 1
13 extents, 1MB each.
For table TAB_SYS, which is located in a system allocation tablespace, we see 86
extents. As expected, the first 16 are 64KB, the next 63 are 1MB, and the last
7 are 8MB.
Now we will delete rows from the tables and shrink the tables to see the extent
map.
frag-code5-jpg
Now the extent map shows:
For table TAB_UNI we see 111 extents, 1MB each. Two extents less than before.
For table TAB_SYS we see 85 extents. One extent less than before. The first 84 e
xtents are exactly as before, while the last one was reduced to just over 6MB. T
his makes sense, since the extents grow in time, and we can allocate extents at
any size.
The last thing well do is to add 2500 rows back to the tables:

frag-code6-jpg
And now the extent map shows:
For table TAB_UNI we see 113 extents, 1MB each. Exactly as in the beginning.
For table TAB_SYS we see 86 extents again. However, the first 84 are exactly the
same as before, and the new one (the 86th) is 8MB, but the 85th extent stayed j
ust over 6MB and didnt grow to 8MB again.
So Where Is The Problem?
The problem resides in something we didnt check or think about. To find the probl
em we need to add to the extent map the physical location of the extent. The loc
ation of the extent in the file is according to the block_id column in DBA_EXTEN
TS table. The block_id column represents the id of the first block in the extent
where 1 is the beginning of the file.
To simplify things, Ill use a single file in the relevant tablespace. This is the
query we will use to see the full map of extents with their location:

frag-code7-jpg
The result of this query will be the file_id of the relevant file, the extent in
formation (block_id and the size) and the content (segment name or free space).
I will not post the entire result set. This is a part from the TBS_UNI result:

frag-code8-jpg
Note the free space after the 6MB extent. Remember the flow that got us to this
situation. We filled the table, then deleted rows, shrank the table and inserted
more rows. At first, the last extent of the table was 8MB in size, and when we
shrank the table, the extent was reduced to about 6MB, releasing about 2MB back
to the tablespace. When we inserted new rows, Oracle needed to allocate a new ex
tent for them; however, it seems that extents cannot start at any block in the f
ile. In our case, the new 8MB extent could not start at block 14224 (which is 11
1.125MB from the beginning of the file), but started at block 14336 which is exa
ctly 112MB from the beginning of the file.
Since this tablespace uses system allocation extent management, other tables tha
t need small extents may allocate this free space. Large tables, however, will n
ot be able to allocate this space, and when allocating their next extent will le
ave an unused area.
To sum up the problem, when we shrink a table in a system allocation extent mana
gement tablespace, a part at the end of the table is released back to the tables
paces free space. Usually, this leaves a smaller than usual last extent in the ta
ble. The next extent of the table will not always be able to start at exactly th
e next block, depending on the size of the requested extent. If this scenario ha
ppens, the space left between the extents can be allocated only for small extent
s, so usually not for extents of the same table or other large tables.
Now, there are two issues to talk about, one is how to defrag a tablespace and t
he other one is how to avoid the fragmentation.
Defrag a Tablespace
If we already have a fragmented tablespace, in order to eliminate the fragmentat
ion we will have to drop the problematic extents. The problem is that we usually c
ant do that as there is too much data in the table and the extents are too close
to the beginning of the table to de-allocate. The only solution I can think of i
s to recreate the table by using the alter table move command or insert select. When
the table is recreated, it allocates a new segment with new extents, releasing
the old segment. After the old segment is dropped, the fragmentation doesnt exist
anymore, but this is a painful operation that requires planning and downtime.
Avoid the Fragmentation
The best thing to do is to avoid this problem altogether. It depends on your spe
cific system and how you use the database. These are some points that might be w
orth considering:
If you use system allocation tablespaces with big tables, and you delete and ins
ert to these tables, you should consider not using the shrink table feature. That
way new rows can use the space the deleted rows left without any problem or frag
mentation.
If you use shrink table on small tables, you probably wont have problems.
If you use shrink table on big tables, but not often, and you also have all kind o
f small tables allocating new extents on this tablespace, the fragmentation issu
e might not be a big one. The few empty spaces caused by the not frequent shrink
table operations will be used by the small tables.
If you only have large tables on a system allocation tablespace and you have to
shrink the tables periodically, consider moving to uniform allocation with adequ
ate extent size to avoid the fragmentation problem.
Summary
The shrink table command is very useful in many cases. However, there are use case
s in which a serious fragmentation might occur. Handling this fragmentation is d
ifficult, so its better to think ahead in order to avoid it.
In this article I tried to give you a real life example I ran into, in order to
help you understand and prevent this fragmentation problem. I hope you will find
it useful in your own environments.

About the Author


Liron is a senior DBA, with over 11 years of experience. During these years Liro
n worked as a senior consultant with a large number of companies in various fiel
ds and managed an Oracle Consulting Team. He mainly specializes in high availabi
lity solutions, performance, backup and recovery, and other infrastructure and a
pplication database areas. He is also a well known senior instructor and lecture
s in Oracle courses, events and forums. Liron is currently the VP of Professiona
l Services at Brillix, a leading Oracle consulting company in Israel.

You might also like