DBA's perform many tasks related to datafiles and tablespaces like creation of them but also creation of segments. Every segment as you know have extents and finally those extents are allocated in Datafiles in blocks. Usually we perform those tasks without thinking what happen behind that process, what happen with extents and the datafiles, how extents are allocated, this is what you will read in this article. In this article I will show you few examples where you will be able to understand how the extents are allocated in datafiles. I will analyse only Locally Managed Tablespaces. If you have been reading my articles you should know already that I like to write my articles with a "Concept" followed by "The example/Internals" fashion. Well, let me give you the Concept of this Article:
"Extents are allocated in datafiles in round-robin Fashion".
Yes, in round-robin fashion. Some people could think that first a datafile is filled up and then the next datafile starts to get filled up but it's not that way. In order to explain you this, let's go to examples.
In this example I will Create a Locally Managed Tablespace with the name "tbslocal" and I will use the table "dgomez".
Note: These examples were applied on the following versions and it's the same behavior, this concept applies as well.
10.2.0.1.0
11.2.0.4.0
12.1.0.1.0
Extent Management Local Uniform:
Creating the tablespace:
SQL> create tablespace tbslocal datafile size 10m, size 10m, size 10m
extent management local uniform size 64k; 2
Tablespace created.
Creating our Segment:
SQL> create table dgomez (id number, value varchar2(40)) tablespace TBSLOCAL;
Table created.
When you create the Table Segment 1 extents is allocated.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
Let's add 2 more extents to the segment manually:
SQL> alter table dgomez allocate extent;
Table altered.
SQL> alter table dgomez allocate extent;
Table altered.
And now let's check the result:
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
7 1 8 64
6 2 8 64
As you can see our extents were allocated in round-robin fashion. But do you remember what kind of tablespace we created? In this example I was using "EXTENT MANAGEMENT LOCAL UNIFORM". There is a little difference between "EXTENT MANAGEMENT LOCAL UNIFORM" and "EXTENT MANAGEMENT LOCAL AUTOALLOCATE" and that difference is what we will see in the following example:
Extent Management Local Autoallocate: With Autoallocate, Oracle tries to understand what kind of segments are being created in this tablespace, it analyse the data and then based on that it creates the extents, next extent could be bigger than the last one. That's why we have a little difference using "Autoallocate".
SQL> drop tablespace tbslocal including contents and datafiles;
Tablespace dropped.
SQL> create tablespace tbslocal datafile size 10m, size 10m, size 10m
extent management local autoallocate; 2
Tablespace created.
SQL> create table dgomez (id number, value varchar2(40)) tablespace TBSLOCAL;
Table created.
First extent created:
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
Allocating a new extent manually:
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
8 1 8 64
It was allocated in the same file? Oracle doesn't allocate extents at a round-robin fashion when we're using "EXTENT MANAGEMENT LOCAL AUTOALLOCATE"?. Perhaps we are missing something here, because Oracle is expensive enough to not have this feature, you know... [;)]
Let's create another extent manually:
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
8 1 8 64
8 2 8 64
No, The same behavior, we are not seeing round-robin. Ok, let me try the last time with 13 more extents:
Creation of 13 extents (13 iterations):
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
8 1 8 64
8 2 8 64
8 3 8 64
8 4 8 64
8 5 8 64
8 6 8 64
8 7 8 64
8 8 8 64
8 9 8 64
8 10 8 64
8 11 8 64
8 12 8 64
8 13 8 64
8 14 8 64
8 15 8 64
16 rows selected.
People could think in this point that with "EXTENT MANAGEMENT LOCAL AUTOALLOCATE" a datafile is filled up first and then another datafile, and so on. But wait, something happens in the extent 16:
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
8 1 8 64
8 2 8 64
8 3 8 64
8 4 8 64
8 5 8 64
8 6 8 64
8 7 8 64
8 8 8 64
8 9 8 64
8 10 8 64
8 11 8 64
8 12 8 64
8 13 8 64
8 14 8 64
8 15 8 64
7 16 128 1024
17 rows selected.
[:O], Finally!!
Now looks like Oracle is using another datafile in the tablespace. I will let Oracle makes me happy again:
4 iterations:
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
8 1 8 64
8 2 8 64
8 3 8 64
8 4 8 64
8 5 8 64
8 6 8 64
8 7 8 64
8 8 8 64
8 9 8 64
8 10 8 64
8 11 8 64
8 12 8 64
8 13 8 64
8 14 8 64
8 15 8 64
7 16 128 1024
6 17 128 1024
8 18 128 1024
7 19 128 1024
6 20 128 1024
21 rows selected.
Fine, our extents started to get allocated at a round-robin fashion. But, does it mean that the round-robin starts in the extent 16? Not at all. it doesn't depend of the Extent 16, we will see this later in the article.
Hey Deiby, but, then the extents are not allocated "evenly" (Evenly is ASM's word for sure).
-Are you sure? Do you know how many blocks are in each datafile?
SQL> select file_id, sum(blocks) from dba_extents where file_id in (6,7,8) group by file_id;
FILE_ID SUM(BLOCKS)
---------- -----------
6 256
8 256
7 256
The 15 first extents have 256 Blocks which is the same than extents after the extent 15.
Now, let's go back and let's answer the question: is it always after extent 16? No.
SQL> drop tablespace tbslocal including contents and datafiles;
Tablespace dropped.
SQL> create tablespace tbslocal datafile size 10m, size 10m, size 10m
extent management local autoallocate; 2
Tablespace created.
SQL> create table dgomez (id number, value varchar2(40)) tablespace TBSLOCAL;
Table created.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
Creation of 2M Extent manually:
SQL> alter table dgomez allocate extent (size 2m);
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
7 1 128 1024
6 2 128 1024
As you can see Oracle didn't create a 2M Extent, instead of that Oracle created 2 Extents of 1M. But there is another interesting thing, starting in the second extent Oracle created the extents at a round-robin fashion. So it depends of extent 16? No. Depends of the the number of blocks already allocated. I could say that it is after 128 blocks allocated Oracle starts to use Round-robin, but we should research more on it. Let's confirm that now we are using round-robin:
SQL> alter table dgomez allocate extent (size 3m);
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
8 0 8 64
7 1 128 1024
6 2 128 1024
8 3 128 1024
7 4 128 1024
6 5 128 1024
6 rows selected.
Confirmed!.
Disadvantage:
Round-Robin is not so well. Unfortunately Oracle only create extents using round-robin but Oracle is not aware of the size of every filesystem so that Oracle cannot create the extents evenly. For example:
- Using ASM: With 2 disks (1G, 100G). For every extent created in the 1G Disk, I will see 10 extents created in the 100G Disk. This is very good because every disk regardless its size will have the same percentage of usage.
- Using Filesystem: with 2 disks (1G, 100G). Indeed you can create 1 datafile in the 1G Disk, and another datafile in the 100G, but oracle always will create 1 extent in each disk, so when the 1G Disk is full the 100G disk will be filled up just at 10%.
As always I recommend strongly using ASM for our datafiles.
SQL> drop tablespace tbslocal including contents and datafiles;
Tablespace dropped.
SQL> create tablespace tbslocal datafile size 10m, size 100m
extent management local uniform size 64k; 2
Tablespace created.
SQL> create table dgomez (id number, value varchar2(40)) tablespace TBSLOCAL;
Table created.
SQL> alter table dgomez allocate extent;
Table altered.
SQL> alter table dgomez allocate extent;
Table altered.
SQL> alter table dgomez allocate extent;
Table altered.
SQL> select file_id, extent_id,blocks, bytes/1024 KB from dba_extents where file_id in (6,7,8) order by 2 ;
FILE_ID EXTENT_ID BLOCKS KB
---------- ---------- ---------- ----------
7 0 8 64
6 1 8 64
7 2 8 64
6 3 8 64
SQL>
Follow me: