21
Segments Shrink Shrink segments online and in real time. Segments that undergo significant data manipulation language (DML) activity, such as UPDATE and DELETE operations, can become sparsely populated, with chunks of free space within their data blocks. Besides simply wasting space, sparsely populated segments can also lead to poor performance, because operations such as a full table scan will need to scan more blocks than necessary to retrieve data. Before Oracle Database 10g, you could reclaim the free segment space by dropping the table, re-creating it, and then reloading the data. You could also use the ALTER TABLE MOVE command to move the table to a different tablespace. Both of these processes, however, must occur with the table offline. Online table reorganization is another way to reclaim space, but it requires significant disk space. Now Shrink With Oracle Database 10g, you can now shrink segments directly, without taking the tablespaces or the objects offline. The process of shrinking a segment includes two key phases: Segment data is compacted. Through a series of INSERT and DELETE statements (during which DML-compatible locks are held on individual rows or blocks of the table), the segment data is moved as far to the beginning of the segment as possible. Given that rowids change, you must enable row movement and also disable any triggers based on rowid for table segments you want to shrink. High-water mark (HWM) is adjusted to an appropriate location (exclusive locks are held on the data at this point), and unused space is deallocated from the segment, so it is available for the tablespace to reallocate to other objects as needed. The shrink capability is implemented in Oracle Database 10g as an optional SHRINK SPACE clause on the ALTER... SQL statements for the associated object. The SHRINK SPACE clause performs both phases of the shrink process. You can also use the optional COMPACT clause in conjunction with the SHRINK SPACE clause to perform just the first phase —the compacting—by itself, to defer the locking of the second phase, for example, and then issue the SHRINK SPACE clause (without COMPACT) later to complete the process, as in ALTER TABLE KIMBERLY.PRODUCT

Oracle 10g Space Mgmt

Embed Size (px)

Citation preview

Page 1: Oracle 10g Space Mgmt

Segments Shrink

Shrink segments online and in real time.

Segments that undergo significant data manipulation language (DML) activity, such as UPDATE and DELETE operations, can become sparsely populated, with chunks of free space within their data blocks. Besides simply wasting space, sparsely populated segments can also lead to poor performance, because operations such as a full table scan will need to scan more blocks than necessary to retrieve data.

Before Oracle Database 10g, you could reclaim the free segment space by dropping the table, re-creating it, and then reloading the data. You could also use the ALTER TABLE MOVE command to move the table to a different tablespace. Both of these processes, however, must occur with the table offline. Online table reorganization is another way to reclaim space, but it requires significant disk space.

Now Shrink

With Oracle Database 10g, you can now shrink segments directly, without taking the tablespaces or the objects offline. The process of shrinking a segment includes two key phases:

Segment data is compacted. Through a series of INSERT and DELETE statements (during which DML-compatible locks are held on individual rows or blocks of the table), the segment data is moved as far to the beginning of the segment as possible. Given that rowids change, you must enable row movement and also disable any triggers based on rowid for table segments you want to shrink.

High-water mark (HWM) is adjusted to an appropriate location (exclusive locks are held on the data at this point), and unused space is deallocated from the segment, so it is available for the tablespace to reallocate to other objects as needed.

The shrink capability is implemented in Oracle Database 10g as an optional SHRINK SPACE clause on the ALTER... SQL statements for the associated object. The SHRINK SPACE clause performs both phases of the shrink process. You can also use the optional COMPACT clause in conjunction with the SHRINK SPACE clause to perform just the first phase—the compacting—by itself, to defer the locking of the second phase, for example, and then issue the SHRINK SPACE clause (without COMPACT) later to complete the process, as in

ALTER TABLE KIMBERLY.PRODUCT SHRINK SPACE COMPACT

and later, run

ALTER TABLE KIMBERLY.PRODUCT SHRINK SPACE

But how do you identify which segments to shrink? And how do you make this process a regular part of maintaining system performance? Fortunately, with Oracle Database 10g, segment usage data is captured, by default, along with all the other statistical data captured by the Automatic Workload Repository (AWR) infrastructure. The segment usage information is easy to obtain with the advisor infrastructure (DBMS_ADVISOR)—specifically, the Segment Advisor, a simple-to-use

Page 2: Oracle 10g Space Mgmt

new feature provided with Oracle Database 10g that identifies which segments have significant free space, and, therefore, are good candidates for segment shrinking.

Getting Started with the Oracle Database 10g Segment Advisor

You can run the Segment Advisor against specific objects (tables, indexes, and materialized views), against an entire tablespace, or against multiple tablespaces.

As with the other advisors provided by Oracle Database 10g, you can launch the Segment Advisor by using Oracle Enterprise Manager Database Control or the DBMS_ADVISOR built-in PL/SQL package.

You can launch the Segment Advisor from several places in the Enterprise Manager Database Control (or Grid Control) browser, such as Advisor Central (from the Enterprise Manager home page), or from the specific database object management page (the Tables or Index page, for example) by selecting Run Segment Advisor from the drop-down menu, with the specific table, index, or materialized view selected.

You can proactively run the Segment Advisor against the specific table you suspect may have a segment usage issue. For example, you might run the Segment Advisor if you've just purged 5,000 old accounts from a 25,000-customer table or run it against a complete tablespace you use as working storage, to stage or cleanse data for a data warehouse.

Whether you launch the Segment Advisor from Advisor Central or within the context of a specific object or tablespace, you initiate a four-page sequence of configuration pages in which you define a Segment Advisor task for submission to the job subsystem.

The four pages of the Segment Advisor wizard step you through the settings for defining the Segment Advisor task's parameters, including the following:

Advisor mode. Can be run in Limited or Comprehensive mode. In Comprehensive mode, when the task runs, the Segment Advisor samples the objects being analyzed, in addition to using already gathered statistics on the objects from the AWR. Limited mode relies on existing statistics only—so if your statistics aren't current (or don't exist at all), Segment Advisor will generate no recommendations.

Time. Limited or unlimited time for analysis by the Segment Advisor task.

Schedule. Whether to run the task immediately or schedule it for later, such as during a maintenance window (this is the default), and whether the task repeats. You can also change the system-generated task name on this page.

Review. Includes a list of your Segment Advisor settings and a Submit button to submit the new task to the job scheduler.

The task is also stored as an object in the AWR (the default retention is for 30 days), so you can rerun it anytime later.

Shrink the Segment

Once the task completes its analysis, you can review the advisor's findings on the Recommendations page (see Figure 1), available from Advisor Central. The page lists all

Page 3: Oracle 10g Space Mgmt

the segments (table, index, and so on) that constitute the object under review. The default view ("View Segments Recommended to Shrink") lists any segments that have free space you can reclaim.

Figure 1: Segment Advisor recommendations

In the example in Figure 1, the Segment Advisor recommends shrinking several segments from different tablespaces (owned by different users). The page shows the segment name, the space allocated to the segment, the used space, the reclaimable space, and recommendations such as "Perform shrink, estimated savings is 14284326 bytes."

Two shrink options are available on this page. In this example, with an index segment selected, "Compact Segments and Release Space" is equivalent to:

ALTER INDEX <INDEX_NAME> SHRINK SPACE

and "Compact Segments" is equivalent to

ALTER INDEX <INDEX_NAME> SHRINK SPACE COMPACT

Page 4: Oracle 10g Space Mgmt

You can choose to implement the recommendation directly from this page, selecting as many tables, indexes, or other listed objects as you like and then clicking on the Schedule Implementation button.

The next page lets you set the time for shrinking the segment or segments selected. Your selection then goes to the job subsystem as a series of SQL statements executed immediately or per your schedule.

Whether you implement a recommendation or simply select Shrink Segment from the drop-down menu on another page of Enterprise Manager, the appropriate SQL statements are submitted to the job subsystem to shrink the segment.

You can also select "View other Segments" to view the status of all other segments and obtain this same level of detail, but in the case of segments in which the advisor doesn't find extra space, recommendations include information such as "The free space in the object is less than the size of the last extent" or "The object has less than 1% free space, it is not worth shrinking."

Using the DBMS_ADVISOR Built-in Package

The Segment Advisor wizard provided by Enterprise Manager Database Control (and Grid Control) uses the functionality of the DBMS_ADVISOR built-in PL/SQL package of the Oracle database. If you prefer, you can call the various subroutines of this package from the command line or by using scripts. Listing 1 shows a script that calls DBMS_ADVISOR and creates a Segment Advisor task.

The DBMS_ADVISOR built-in PL/SQL package, new with Oracle Database 10g, lets you create the complete array of advisor tasks, such as SQL Tuning Advisor and SQL Access Advisor, many of which previous Talking Tuning columns have discussed. The Segment Advisor is another subsystem (or set of procedures) available in that package.

Code Listing 1: Script for creating a Segment Advisor task on a table

VARIABLE ID NUMBER; BEGIN DECLARE TASK_ID NUMBER; NAME VARCHAR2(100) ; DESCR VARCHAR2(500) ; OBJID NUMBER; BEGIN NAME := '' ; DESCR := 'SEGMENT ADVISOR ON A TABLE'; DBMS_ADVISOR.CREATE_TASK('SEGMENT ADVISOR', :ID, NAME, DESCR, NULL); DBMS_ADVISOR.CREATE_OBJECT(NAME, 'TABLE', 'KIMBERLY','PRODUCT', NULL, NULL, OBJID); DBMS_ADVISOR.SET_TASK_PARAMETER(NAME, 'RECOMMEND_ALL', 'TRUE'); DBMS_ADVISOR.EXECUTE_TASK(NAME); END; END;

Page 5: Oracle 10g Space Mgmt

Conclusion

Whether you use Enterprise Manager or the DBMS_ADVISOR package, the Segment Advisor is easy to run and lets you quickly find areas in your database where you can reclaim space. It finds the pockets of reclaimable space in segments and then, rather than making you unload the table and rebuild it offline, lets you shrink segments online and in place. No additional storage is needed, because the operation effectively does an INSERT and a DELETE right in the object itself.

Space, Object, and Transaction Management in Oracle Database 10g

This article describes the new features related to space, object and transaction management in Oracle 10g.

Automatic Undo Retention Tuning Undo Advisor Segment Advisor Online Segment Shrink New Segment Resource Estimation

Automatic Undo Retention Tuning

Oracle 10g automatically tunes undo retention to reduce the chances of "snapshot too old" errors during long-running queries. The UNDO_RETENTION parameter is used to set a low retention time threshold which the system will attempt to achieve. In the event of any undo space constraints the system will prioritize DML operations over undo retention meaning the low threshold may not be achieved. If the undo retention threshold must be guaranteed, even at the expense of DML operations, the RETENTION GUARANTEE clause can be set against the undo tablespace during or after creation:-- Reset the undo low threshold.ALTER SYSTEM SET UNDO_RETENTION = 2400;

-- Guarantee the minimum threshold is maintained.ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;

SELECT tablespace_name, retention FROM dba_tablespaces;

TABLESPACE_NAME RETENTION------------------------------ -----------SYSTEM NOT APPLYUNDOTBS1 GUARANTEESYSAUX NOT APPLYTEMP NOT APPLYUSERS NOT APPLY

5 rows selected.

-- Switch back to the default mode.ALTER TABLESPACE undotbs1 RETENTION NOGUARANTEE;

TABLESPACE_NAME RETENTION------------------------------ -----------SYSTEM NOT APPLYUNDOTBS1 NOGUARANTEESYSAUX NOT APPLY

Page 6: Oracle 10g Space Mgmt

TEMP NOT APPLYUSERS NOT APPLY

5 rows selected.As the name suggests, the NOT APPLY value is assigned to non-undo tablespaces for which this functionality does not apply.

Undo Advisor

The Undo Advisor in Enterprise Manager (Home > Advisor Central > Undo Management > Undo Advisor) provides recommendations for undo configuration. The Undo Advisor is also accessible from PL/SQL using the DBMS_ADVISOR package, but none of the reporting procedures support this advisor so you must access the recommendations from the DBA_ADVISOR_% views manually:SELECT MIN(snap_id), MAX(snap_id) FROM dba_hist_snapshot;

MIN(SNAP_ID) MAX(SNAP_ID)------------ ------------ 884 1052

1 row selected.

DECLARE l_task_name VARCHAR2(30) := '884_1052_AWR_SNAPSHOT_UNDO'; l_object_id NUMBER;BEGIN -- Create an ADDM task. DBMS_ADVISOR.create_task ( advisor_name => 'Undo Advisor', task_name => l_task_name, task_desc => 'Undo Advisor Task');

DBMS_ADVISOR.create_object ( task_name => l_task_name, object_type => 'UNDO_TBS', attr1 => NULL, attr2 => NULL, attr3 => NULL, attr4 => 'null', attr5 => NULL, object_id => l_object_id);

-- Set the target object. DBMS_ADVISOR.set_task_parameter ( task_name => l_task_name, parameter => 'TARGET_OBJECTS', value => l_object_id);

-- Set the start and end snapshots. DBMS_ADVISOR.set_task_parameter ( task_name => l_task_name, parameter => 'START_SNAPSHOT', value => 884);

DBMS_ADVISOR.set_task_parameter (

Page 7: Oracle 10g Space Mgmt

task_name => l_task_name, parameter => 'END_SNAPSHOT', value => 1052);

-- Execute the task. DBMS_ADVISOR.execute_task(task_name => l_task_name);END;/

Segment Advisor

The segment advisor performs analysis on the fragmentation of specified tablespaces, segments or objects and makes recommendations on how space can be reclaimed. The advisor is accessible from Enterprise Manager (Home > Advisor Central > Segment Advisor) or from PL/SQL by using the DBMS_ADVISOR package:DECLARE l_object_id NUMBER;BEGIN -- Create a segment advisor task for the SCOTT.EMP table. DBMS_ADVISOR.create_task ( advisor_name => 'Segment Advisor', task_name => 'EMP_SEGMENT_ADVISOR', task_desc => 'Segment Advisor For EMP');

DBMS_ADVISOR.create_object ( task_name => 'EMP_SEGMENT_ADVISOR', object_type => 'TABLE', attr1 => 'SCOTT', attr2 => 'EMP', attr3 => NULL, attr4 => 'null', attr5 => NULL, object_id => l_object_id);

DBMS_ADVISOR.set_task_parameter ( task_name => 'EMP_SEGMENT_ADVISOR', parameter => 'RECOMMEND_ALL', value => 'TRUE');

DBMS_ADVISOR.execute_task(task_name => 'EMP_SEGMENT_ADVISOR');

-- Create a segment advisor task for the USERS tablespace. DBMS_ADVISOR.create_task ( advisor_name => 'Segment Advisor', task_name => 'USERS_SEGMENT_ADVISOR', task_desc => 'Segment Advisor For USERS');

DBMS_ADVISOR.create_object ( task_name => 'USERS_SEGMENT_ADVISOR', object_type => 'TABLESPACE', attr1 => 'USERS', attr2 => NULL, attr3 => NULL, attr4 => 'null', attr5 => NULL, object_id => l_object_id);

Page 8: Oracle 10g Space Mgmt

DBMS_ADVISOR.set_task_parameter ( task_name => 'USERS_SEGMENT_ADVISOR', parameter => 'RECOMMEND_ALL', value => 'TRUE');

DBMS_ADVISOR.execute_task(task_name => 'USERS_SEGMENT_ADVISOR');END;/

-- Display the findings.SET LINESIZE 250COLUMN task_name FORMAT A20COLUMN object_type FORMAT A20COLUMN schema FORMAT A20COLUMN object_name FORMAT A30COLUMN object_name FORMAT A30COLUMN message FORMAT A40COLUMN more_info FORMAT A40

SELECT f.task_name, f.impact, o.type AS object_type, o.attr1 AS schema, o.attr2 AS object_name, f.message, f.more_infoFROM dba_advisor_findings f JOIN dba_advisor_objects o ON f.object_id = o.object_id AND f.task_name = o.task_nameWHERE f.task_name IN ('EMP_SEGMENT_ADVISOR', 'USERS_SEGMENT_ADVISOR')ORDER BY f.task_name, f.impact DESC;

Online Segment Shrink

Based on the recommendations from the segment advisor you can recover space from specific objects using one of the variations of the ALTER TABLE ... SHRINK SPACE command:-- Enable row movement.ALTER TABLE scott.emp ENABLE ROW MOVEMENT;

-- Recover space and amend the high water mark (HWM).ALTER TABLE scott.emp SHRINK SPACE;

-- Recover space, but don't amend the high water mark (HWM).ALTER TABLE scott.emp SHRINK SPACE COMPACT;

-- Recover space for the object and all dependant objects.ALTER TABLE scott.emp SHRINK SPACE CASCADE;The shrink is accomplished by moving rows between blocks, hence the requirement for row movement to be enabled for the shrink to take place. This can cause problem with ROWID based triggers. The shrinking process is only available for objects in tablespaces with automatic segment-space management enabled.

The COMPACT option allows the shrink operation to be broken into two stages. First the rows are moved using the COMPACT option but the HWM is not adjusted so no parsed SQL statements are invalidated. The HWM can be adjusted at a later date by reissuing the statement without the

Page 9: Oracle 10g Space Mgmt

COMPACT option. At this point any depenedant SQL statements will need to be reparsed.

New Segment Resource Estimation

Additions to the DBMS_SPACE package allow segment sizes to be estimated before they are actually created, enabling the DBA to organize disk space in advance:SET SERVEROUTPUT ONDECLARE l_ddl VARCHAR2(500); l_used_bytes NUMBER; l_alloc_bytes NUMBER;BEGIN -- Estimate the size of a new table on the USERS tablespace. DBMS_SPACE.create_table_cost ( tablespace_name => 'USERS', avg_row_size => 106, row_count => 1000000, pct_free => 10, used_bytes => l_used_bytes, alloc_bytes => l_alloc_bytes); DBMS_OUTPUT.put_line ('new table (TS=USERS): used=' || l_used_bytes || ' bytes allocated=' || l_alloc_bytes || ' bytes');

-- Estimate the size of a new index. l_ddl := 'CREATE INDEX scott.emp_idx_1 ON scott.emp(job, mgr, hiredate)'; DBMS_SPACE.create_index_cost ( ddl => l_ddl, used_bytes => l_used_bytes, alloc_bytes => l_alloc_bytes); DBMS_OUTPUT.put_line ('scott.emp_idx_1 : used=' || l_used_bytes || ' bytes allocated=' || l_alloc_bytes || ' bytes');END;/

new table (TS=USERS): used=124125184 bytes allocated=125829120 bytesscott.emp_idx_1 : used=280 bytes allocated=65536 bytes

PL/SQL procedure successfully completed.The OBJECT_GROWTH_TREND pipelined function uses information from the AWR to display information about growth trends for specific objects:COLUMN timepoint FORMAT A30

SELECT *FROM TABLE(DBMS_SPACE.object_growth_trend ('SCOTT','EMP','TABLE'))ORDER BY timepoint;

TIMEPOINT SPACE_USAGE SPACE_ALLOC QUALITY------------------------------ ----------- ----------- --------------------

Page 10: Oracle 10g Space Mgmt

11-APR-04 02.55.14.116000 PM 6372 65536 INTERPOLATED12-APR-04 02.55.14.116000 PM 6372 65536 INTERPOLATED13-APR-04 02.55.14.116000 PM 6372 65536 INTERPOLATED...13-MAY-04 02.55.14.116000 PM 6372 65536 PROJECTED14-MAY-04 02.55.14.116000 PM 6372 65536 PROJECTED15-MAY-04 02.55.14.116000 PM 6372 65536 PROJECTED16-MAY-04 02.55.14.116000 PM 6372 65536 PROJECTED

36 rows selected.The QUALITY column indicates the quality of the output as follows:

GOOD - The data for the timepoint relates to data within the AWR repository with a timestamp withinn 10% of the interval.

INTERPOLATED - The data for this timepoint did not meet the GOOD criteria but was based on data gathered before and after the timepoint.

PROJECTED - The timepoint is in the future, so the data is estimated based on previous growth statistics.

Page 11: Oracle 10g Space Mgmt

Reclaiming Unused LOB Space

Overview

Manually reclaiming unused space in a normal Oracle table is a fairly simple process and can be performed online starting with Oracle 10g R1 using:

SQL> ALTER TABLE <table_name> SHRINK SPACE COMPACT;

For example, to reclaim space from the table mytable:

SQL> ALTER TABLE mytable ENABLE ROW MOVEMENT;

Table altered.

SQL> ALTER TABLE mytable SHRINK SPACE;

Table altered.

What if, however, the table contains a LOB column that contains significant unused space? Starting with Oracle 10g R2, Oracle provides a solution that allows users to reclaim LOB space (LOB data and LOB index) and that is the topic of this article.

The syntax used to reclaim LOB space is:

SQL> ALTER TABLE <table_name> MODIFY LOB (<lob_column>) (SHRINK SPACE);

 

The alter table <table_name> shrink space statement was introduced in Oracle 10g R1. The ability to extend the SHRINK SPACE command to LOBs was introduced in Oracle 10g R2 - the focus of this article. This new feature allows users to remove the deleted and free space altogether from a LOB segment and LOB index.

Example

1. Example binary image file to load into BLOB column:

Any Image to be inserted

2. Create example table to store binary images into a LOB column:

DROP TABLE test_lob CASCADE CONSTRAINTS/

Table dropped.

CREATE TABLE test_lob ( id NUMBER , file_name VARCHAR2(45) , image BLOB

Page 12: Oracle 10g Space Mgmt

, timestamp DATE)/

Table created.

3. Create Oracle sequence to track images:

DROP SEQUENCE test_lob_seq/

Sequence dropped.

CREATE SEQUENCE test_lob_seq/

Sequence created.

4. Create Oracle directory for binary image files:

CREATE OR REPLACE DIRECTORY images_dirAS '/u03/oradir/images'/

Directory created.

5. Create a sample PL/SQL procedure to load images from the file system to a BLOB column:

load_blob_from_file_image.sql

CREATE OR REPLACE PROCEDURE Load_BLOB_From_File_ImageAS

dest_loc BLOB; file_name TEST_LOB.FILE_NAME%TYPE := 'iDevelopment_info_logo_2.tif'; src_loc BFILE := BFILENAME('IMAGES_DIR', file_name);

BEGIN

-- +-------------------------------------------------------------+ -- | INSERT INITIAL BLOB VALUE (an image file) INTO THE TABLE | -- +-------------------------------------------------------------+ INSERT INTO test_lob (id, file_name, image, timestamp) VALUES (test_lob_seq.nextval, file_name, empty_blob(), sysdate) RETURNING image INTO dest_loc;

-- +-------------------------------------------------------------+ -- | OPENING THE SOURCE BFILE IS MANDATORY | -- +-------------------------------------------------------------+ DBMS_LOB.OPEN(src_loc, DBMS_LOB.LOB_READONLY);

Page 13: Oracle 10g Space Mgmt

-- +-------------------------------------------------------------+ -- | OPENING THE LOB IS OPTIONAL | -- +-------------------------------------------------------------+ DBMS_LOB.OPEN(dest_loc, DBMS_LOB.LOB_READWRITE);

-- +-------------------------------------------------------------+ -- | SIMPLY CALL "loadfromfile" TO LOAD FILES INTO A LOB COLUMN | -- +-------------------------------------------------------------+ DBMS_LOB.LOADFROMFILE( dest_lob => dest_loc , src_lob => src_loc , amount => DBMS_LOB.getLength(src_loc));

-- +-------------------------------------------------------------+ -- | CLOSING ANY LOB IS MANDATORY IF YOU HAVE OPENED IT | -- +-------------------------------------------------------------+ DBMS_LOB.CLOSE(dest_loc); DBMS_LOB.CLOSE(src_loc);

COMMIT;

END;/

SQL> @load_blob_from_file_image.sql

Procedure created.

6. Run script to load 1,000 images (25MB) to LOB column:

BEGIN FOR i IN 1 .. 1000 LOOP Load_BLOB_From_File_Image(); END LOOP;END;/

PL/SQL procedure successfully completed.

SELECT count(1) FROM test_lob;

COUNT(1)---------- 1000

7. Determine name and size of the LOB column:

SELECT table_name, column_name, segment_name, a.bytesFROM dba_segments a JOIN dba_lobs b

Page 14: Oracle 10g Space Mgmt

USING (owner, segment_name)WHERE b.table_name = 'TEST_LOB';

TABLE_NAME COLUMN_NAME SEGMENT_NAME BYTES------------ -------------- ---------------------------- ----------TEST_LOB IMAGE SYS_LOB0000054349C00003$$ 25,165,824

SELECT NVL((SUM(DBMS_LOB.GETLENGTH(image))),0) AS BYTESFROM test_lob;

BYTES----------16,706,000

8. Now let's delete all images (BLOBS) and see what the size is after:

DELETE FROM test_lob;

1000 rows deleted.

COMMIT;

Commit complete.

SELECT table_name, column_name, segment_name, a.bytesFROM dba_segments a JOIN dba_lobs bUSING (owner, segment_name)WHERE b.table_name = 'TEST_LOB';

TABLE_NAME COLUMN_NAME SEGMENT_NAME BYTES------------ -------------- ---------------------------- ----------TEST_LOB IMAGE SYS_LOB0000054349C00003$$ 25,165,824

SELECT NVL((SUM(DBMS_LOB.GETLENGTH(image))),0) AS BYTESFROM test_lob;

BYTES---------- 0

9. Hmmm, so it looks like the images are gone, but the space is still allocated within the LOBSEGMENT (25MB). Ok, so maybe if we insert data back into the table (more importantly, the LOB column), that space will be recycled:

BEGIN FOR i IN 1 .. 1000 LOOP Load_BLOB_From_File_Image(); END LOOP;

Page 15: Oracle 10g Space Mgmt

END;/

PL/SQL procedure successfully completed.

SELECT count(1) FROM test_lob;

COUNT(1)---------- 1000

SELECT table_name, column_name, segment_name, a.bytesFROM dba_segments a JOIN dba_lobs bUSING (owner, segment_name)WHERE b.table_name = 'TEST_LOB';

TABLE_NAME COLUMN_NAME SEGMENT_NAME BYTES------------ -------------- ---------------------------- ----------TEST_LOB IMAGE SYS_LOB0000054349C00003$$ 50,331,648

SELECT NVL((SUM(DBMS_LOB.GETLENGTH(image))),0) AS BYTESFROM test_lob;

BYTES----------16,706,000

10. Ok, so I was wrong. The LOB space did not get recycled with the new data. Let's now pull out the big guns and manually shrink the LOB segment to free up the space immediately:

DELETE FROM test_lob;

1000 rows deleted.

COMMIT;

Commit complete.

ALTER TABLE test_lob MODIFY LOB (image) (SHRINK SPACE);

Table altered.

SELECT table_name, column_name, segment_name, a.bytesFROM dba_segments a JOIN dba_lobs bUSING (owner, segment_name)WHERE b.table_name = 'TEST_LOB';

TABLE_NAME COLUMN_NAME SEGMENT_NAME BYTES------------ -------------- ---------------------------- ----------

Page 16: Oracle 10g Space Mgmt

TEST_LOB IMAGE SYS_LOB0000054349C00003$$ 65,536

SELECT NVL((SUM(DBMS_LOB.GETLENGTH(image))),0) AS BYTESFROM test_lob;

BYTES---------- 0

11. Now that looks better!

Troubleshooting

Pre-requisites

The alter table <table_name> shrink space statement was introduced in Oracle 10g R1. The ability to extend the SHRINK SPACE command to LOBs was introduced in Oracle 10g R2 - the focus of this article. This new feature allows users to remove the deleted and free space altogether from a LOB segment and LOB index.

The LOB segment must reside in an ASSM tablespace.

Row movement on a table is only required if you are moving rows from the table itself. It is not required if all you are doing is shrinking its LOB segment(s).

Excessive Redo Generated

Shrinking a LOB segment does generate redo. For example, shrinking a 36GB LOB will generate approximately 36GB of redo! Make certain you have an adequate amount of disk space for any archived redo log files before manually shrinking a LOB segment.

The CASCADE Option

The alter table <table_name> shrink space statement has an optional CASCADE clause that shrinks all dependent objects (including LOBS) along with the table data itself. For example:

ALTER TABLE test_lob ENABLE ROW MOVEMENT;

Table altered.

ALTER TABLE test_lob SHRINK SPACE CASCADE;

Table altered.

With Oracle 10g R1, when shrinking a table, the CASCADE option DOES NOT shrink LOB segments for that table.

Page 17: Oracle 10g Space Mgmt

With Oracle 10g R2 and higher, when shrinking a table, the CASCADE option DOES shrink all LOB segments (and indexes) for that table.