Here’s another one of those little changes that sidles in when you’re not looking.
When locally managed tablespaces first appeared, there were a number of posts on Usenet (comp.databases.oracle.server) and the metalink lists (the OTN database forum didn’t exist at the time) about “missing” space in data files. The commonest sort of comment was along the lines of
“I’ve created a data file of 100 MB, how come I can only create 99 extents of 1 MB each?”
“I’ve created a data file of 10 GB, how come I can only create 9 extents of 1 GB each?”
The answer was that Oracle reserved the first few blocks of the file (typically totalling 64KB of space, but 128KB if you were on a platform that supported a 32KB block size) for space management blocks holding a bitmap identifying which (notional) extents in the file were free and which were allocated to data segments. For uniform extents each bit in the map represented the given unit size of an extent, for system-managed extent allocation each bit represented 64KB (the “lowest common denominator” for an extent). As a side effect of this bitmap/extent mapping you can “lose” a whole extent – less one block – if you don’t work out your file size quite carefully.
Here’s a little demo script, with some results, cut from a session using 10.2.0.3 to demonistrate the point:
create
tablespace tiny
datafile 'C:\ORACLE\ORADATA\D10g\tiny.dbf'
SIZE 1114112 reuse
extent management local
autoallocate
segment space management auto
;
select
file_id, block_id, bytes, blocks
from
dba_free_space
where
tablespace_name = 'TINY'
;
SQL> @demo
Tablespace created.
FILE_ID BLOCK_ID BYTES BLOCKS
---------- ---------- ---------- ----------
8 9 1048576 128
1 row selected.
SQL>
If you’re wondering about my choice of initial file size, it’s the equivalent of 1MB + 64KB. As you can see this results in 1MB of “user” space available, starting in block 9 of the file (leaving 8 blocks – 64KB given my block size – for any file-based overheads).
Let’s check the results (after changing the filename) for an 11g instance – 11.1.0.7 in this case:
SQL> @temp
Tablespace created.
FILE_ID BLOCK_ID BYTES BLOCKS
---------- ---------- ---------- ----------
7 128 65536 8
1 row selected.
SQL>
When we shift to 11g we see 1MB of overhead at the start of the file, and only 64KB left for user space.
I haven’t done a lot of testing to see how many different special cases there are but based on a couple of quick checks it looks as if Oracle will allocate 1MB of space management overhead at the start of file if the initial file size is at least 1MB + 64KB. (For smaller files the overhead is still 64KB.)
I suspect the reason behind this is that if a file were to become very large Oracle would eventually have to allocate a secondary space management bitmap somewhere in the middle of the file (which might make it hard to shrink the file at a later date), so it pre-emptively allocates a space management area large enough for a very large file when you create the initial file.
As a little throwaway test (to see if I could get a secondary map allocated) I created a single file of 2,047 MB, in a tablespace using locally managed extents of uniform size 16KB (yes, deliberately silly sizing), and freelist management. Here’s the slightly surprising result I got from querying dba_free_space for that tablespace:
select
block_id, blocks,
block_id + blocks - 1 end_block,
bytes/1048576 MB
from
dba_free_space
where
tablespace_name = 'TINY'
order by
block_id
;
BLOCK_ID BLOCKS END_BLOCK MB
---------- ---------- ---------- ----------
128 126976 127103 992
127104 126976 254079 992
254080 7936 262015 62
----------
sum 2046
3 rows selected.
I was expecting a single free space chunk – but that’s not the way it seems to work. For an 8KB block size (in this version of Oracle), the bitmap space management blocks start at block 3 of the file, and each bitmap block can map 63,488 extents – which in my case amounted to 126,976 blocks – and the code that reports dba_free_space seems to look at one bitmap block at a time to generate the report.
It’s probably the case that none of this matters to anyone – but it’s just another couple of details that go into my catalogue of implementation details just in case I find the boundary condition one day, perhaps relating to LOBs or SecureFiles, where something strange happens because of some side effect of this implementation.
Footnote: If you want to create a file on an 8KB block size with a secondary bitmap, you should start with a small file (1MB or less), 16KB uniform extents and freelist management; this will give you 6 blocks of bitmaps, which can each map 63,488 extent, or 126,976 blocks, for a total of 5,952MB. Add 64KB for the initial file header information and then a bit more – call it 6GB to make it easy – and you’ve got a targer to resize the file to the point where you get a secondary map. But I think that means you’ll need a 64-bit O/S.

Very Interesting.
Comment by baskar — June 1, 2012 @ 3:27 am UTC Jun 1,2012 |
Reblogged this on lava kafle kathmandu nepal.
Comment by lkafle — June 1, 2012 @ 3:44 am UTC Jun 1,2012 |
[...] Jonathan Lewis starts with the sentence, “When locally managed tablespaces first appeared, there were a number of posts on Usenet (comp.databases.oracle.server) and the metalink lists (the OTN database forum didn’t exist at the time) about “missing” space in data files.” [...]
Pingback by Log Buffer #274, A Carnival of the Vanities for DBAs | The Pythian Blog — June 1, 2012 @ 7:01 am UTC Jun 1,2012 |
Jonathan,
I think it’s more likely they did this for alignment reasons. I wonder if they also align segments on the MB boundary (when using auto-sizing) inside the datafiles as well.
Comment by Christo Kutrovsky — June 1, 2012 @ 6:39 pm UTC Jun 1,2012 |
Christo,
That sounds like a reasonable hypothesis, especially when you start thinking about ASM and AUs of 1MB and 4MB, and the impact of Exadata striping across cells. You could probably imagine seeing some sort of performance side effect if the extent boundaries on your objects were 64KB out of step with the AU boundary.
Comment by Jonathan Lewis — June 1, 2012 @ 7:54 pm UTC Jun 1,2012 |
[...] Thanks to Jonathan Lewis Sir for pointing that out. Please go through Jonathan’s blog http://jonathanlewis.wordpress.com/2012/05/31/lmt-headers/ to get a clear idea of what these LMT headers [...]
Pingback by DBA_DATA_FILES, DBA_FREE_SPACE and DBA_SEGMENTS–A Myth Buster | queryCSM — March 26, 2013 @ 3:41 pm UTC Mar 26,2013 |
Jonathan,
the change seems to be introduced for extent alignment reasons (as already pointed out by Christo), and the behaviour can be controlled via event 60060 as I’ve recently learned, which disables or enables the extent alignment on allocation unit boundaries.
Enabling the event will revert to the pre-11g result for your test case, but has some more significant meaning for extent allocation in general (will publish an article soon).
Randolf
Comment by Randolf Geist — April 17, 2013 @ 7:14 pm UTC Apr 17,2013 |