Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 14 ■ PARALLEL EXECUTION 631 This sounds all right at first, but in a data warehouse environment, this can lead to “wastage” after a large load. Let’s say you want to load 1,010MB of data (about 1GB), and you are using a tablespace with 100MB extents. You decide to use ten parallel execution servers to load this data. Each would start by allocating its own 100MB extent (there will be ten of them in all) and filling it up. Since each has 101MB of data to load, it would fill up its first extent and then proceed to allocate another 100MB extent, of which it would use 1MB. You now have 20 extents, 10 of which are full and 10 of which have 1MB each, and 990MB is “allocated but not used.” This space could be used the next time you load, but right now you have 990MB of dead space. This is where extent trimming comes in. Oracle will attempt to take the last extent of each parallel execution server and “trim” it back to the smallest size possible. Extent Trimming and Dictionary-Managed Tablespaces If you are using legacy dictionary-managed tablespaces, then Oracle will be able to convert each of the 100MB extents that contain just 1MB of data into 1MB extents. Unfortunately, that would (in dictionary-managed tablespaces) tend to leave ten noncontiguous 99MB extents free, and since your allocation scheme was for 100MB extents, this 990MB of space would not be very useful! The next allocation of 100MB would likely not be able to use the existing space, since it would be 99MB of free space, followed by 1MB of allocated space, followed by 99MB of free space, and so on. We will not review the dictionary-managed approach further in this book. Extent Trimming and Locally-Managed Tablespaces Enter locally-managed tablespaces. Here we have two types: UNIFORM SIZE, whereby every extent in the tablespace is always precisely the same size, and AUTOALLOCATE, whereby Oracle decides how big each extent should be using an internal algorithm. Both of these approaches solve nicely the problem of the 99MB of free space, followed by 1MB of used space, followed by 99MB of free space, and so on, resulting in lots of free space that cannot be used. However, they each solve it very differently. The UNIFORM SIZE approach obviates extent trimming from consideration all together. When you use UNIFORM SIZEs, Oracle cannot perform extent trimming. All extents are of that single size—none can be smaller (or larger) than that single size. AUTOALLOCATE extents, on the other hand, do support extent trimming, but in an intelligent fashion. They use a few specific sizes of extents and have the ability to use space of different sizes—that is, the algorithm permits the use of all free space over time in the tablespace. Unlike the dictionary-managed tablespace, where if you request a 100MB extent, Oracle will fail the request if it can find only 99MB free extents (so close, yet so far), a locally-managed tablespace with AUTOALLOCATE extents can be more flexible. It may reduce the size of the request it was making in order to attempt to use all of the free space. Let’s now look at the differences between the two locally-managed tablespace approaches. To do that, we need a real-life example to work with. We’ll set up an external table capable of being used in a parallel direct path load situation, which is something that we do frequently. Even if you are still using SQL*Loader to parallel direct path load data, this section applies entirely—you just have manual scripting to do to actually load the data. So, in order to investigate extent trimming, we need to set up our example load and then perform the loads under varying conditions and examine the results.

632 CHAPTER 14 ■ PARALLEL EXECUTION Setting Up To get started, we need an external table. I’ve found time and time again that I have a legacy control file from SQL*Loader that I used to use to load data. One that looks like this, for example: LOAD DATA INFILE '/tmp/big_table.dat' INTO TABLE big_table REPLACE FIELDS TERMINATED BY '|' ( id ,owner ,object_name ,subobject_name ,object_id ,data_object_id ,object_type ,created ,last_ddl_time ,timestamp ,status ,temporary ,generated ,secondary ) We can convert this easily into an external table definition using SQL*Loader itself: $ sqlldr big_table/big_table big_table.ctl external_table=generate_only SQL*Loader: Release 10.1.0.3.0 - Production on Mon Jul 11 14:16:20 2005 Copyright (c) 1982, 2004, Oracle. All rights reserved. Notice the parameter EXTERNAL_TABLE passed to SQL*Loader. It causes SQL*Loader in this case to not load data, but rather to generate a CREATE TABLE statement for us in the log file. This CREATE TABLE statement looked as follows (this is an abridged form; I’ve edited out repetitive elements to make the example smaller): CREATE TABLE "SYS_SQLLDR_X_EXT_BIG_TABLE" ( "ID" NUMBER, ... "SECONDARY" VARCHAR2(1) ) ORGANIZATION external ( TYPE oracle_loader DEFAULT DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE CHARACTERSET WE8ISO8859P1 BADFILE 'SYS_SQLLDR_XT_TMPDIR_00000':'big_table.bad' LOGFILE 'big_table.log_xt' READSIZE 1048576 FIELDS TERMINATED BY "|" LDRTRIM REJECT ROWS WITH ALL NULL FIELDS ( "ID" CHAR(255) TERMINATED BY "|", .... "SECONDARY" CHAR(255)

CHAPTER 14 ■ PARALLEL EXECUTION 631<br />

This sounds all right at first, but in a data warehouse environment, this can lead to<br />

“wastage” after a large load. Let’s say you want to load 1,010MB of data (about 1GB), <strong>and</strong> you<br />

are using a tablespace with 100MB extents. You decide to use ten parallel execution servers to<br />

load this data. Each would start by allocating its own 100MB extent (there will be ten of them<br />

in all) <strong>and</strong> filling it up. Since each has 101MB of data to load, it would fill up its first extent <strong>and</strong><br />

then proceed to allocate another 100MB extent, of which it would use 1MB. You now have<br />

20 extents, 10 of which are full <strong>and</strong> 10 of which have 1MB each, <strong>and</strong> 990MB is “allocated but<br />

not used.” This space could be used the next time you load, but right now you have 990MB of<br />

dead space. This is where extent trimming comes in. <strong>Oracle</strong> will attempt to take the last extent<br />

of each parallel execution server <strong>and</strong> “trim” it back to the smallest size possible.<br />

Extent Trimming <strong>and</strong> Dictionary-Managed Tablespaces<br />

If you are using legacy dictionary-managed tablespaces, then <strong>Oracle</strong> will be able to convert<br />

each of the 100MB extents that contain just 1MB of data into 1MB extents. Unfortunately, that<br />

would (in dictionary-managed tablespaces) tend to leave ten noncontiguous 99MB extents<br />

free, <strong>and</strong> since your allocation scheme was for 100MB extents, this 990MB of space would not<br />

be very useful! The next allocation of 100MB would likely not be able to use the existing space,<br />

since it would be 99MB of free space, followed by 1MB of allocated space, followed by 99MB of<br />

free space, <strong>and</strong> so on. We will not review the dictionary-managed approach further in this book.<br />

Extent Trimming <strong>and</strong> Locally-Managed Tablespaces<br />

Enter locally-managed tablespaces. Here we have two types: UNIFORM SIZE, whereby every<br />

extent in the tablespace is always precisely the same size, <strong>and</strong> AUTOALLOCATE, whereby <strong>Oracle</strong><br />

decides how big each extent should be using an internal algorithm. Both of these approaches<br />

solve nicely the problem of the 99MB of free space, followed by 1MB of used space, followed<br />

by 99MB of free space, <strong>and</strong> so on, resulting in lots of free space that cannot be used. However,<br />

they each solve it very differently.<br />

The UNIFORM SIZE approach obviates extent trimming from consideration all together.<br />

When you use UNIFORM SIZEs, <strong>Oracle</strong> cannot perform extent trimming. All extents are of that<br />

single size—none can be smaller (or larger) than that single size.<br />

AUTOALLOCATE extents, on the other h<strong>and</strong>, do support extent trimming, but in an intelligent<br />

fashion. They use a few specific sizes of extents <strong>and</strong> have the ability to use space of different<br />

sizes—that is, the algorithm permits the use of all free space over time in the tablespace.<br />

Unlike the dictionary-managed tablespace, where if you request a 100MB extent, <strong>Oracle</strong> will<br />

fail the request if it can find only 99MB free extents (so close, yet so far), a locally-managed<br />

tablespace with AUTOALLOCATE extents can be more flexible. It may reduce the size of the<br />

request it was making in order to attempt to use all of the free space.<br />

Let’s now look at the differences between the two locally-managed tablespace approaches.<br />

To do that, we need a real-life example to work with. We’ll set up an external table capable of<br />

being used in a parallel direct path load situation, which is something that we do frequently.<br />

Even if you are still using SQL*Loader to parallel direct path load data, this section applies<br />

entirely—you just have manual scripting to do to actually load the data. So, in order to investigate<br />

extent trimming, we need to set up our example load <strong>and</strong> then perform the loads under<br />

varying conditions <strong>and</strong> examine the results.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!