12.1.2.2 The DBMS_SPACE.UNUSED_SPACE procedure The UNUSED_SPACE procedure returns information about the unused space and the position of the highwater mark in a table, index, or cluster
Trang 1For more information about freelists and how they can be used to minimize contention, see the Oracle7
Parallel Server Concepts and Administration manual.
12.1.2.2 The DBMS_SPACE.UNUSED_SPACE procedure
The UNUSED_SPACE procedure returns information about the unused space and the position of the
highwater mark in a table, index, or cluster segment Specifications for Oracle7 and Oracle8 differ as follows Here is the Oracle 7.x specification:
PROCEDURE DBMS_SPACE.UNUSED_SPACE
(segment_owner IN VARCHAR2
,segment_name IN VARCHAR2
,segment_type IN VARCHAR2
,total_blocks OUT NUMBER
,total_bytes OUT NUMBER
,unused_blocks OUT NUMBER
,unused_bytes OUT NUMBER
,last_used_extent_file_id OUT NUMBER
,last_used_extent_block_id OUT NUMBER
,last_used_block OUT NUMBER);
Here is the Oracle 8.0 specification:
PROCEDURE DBMS_SPACE.UNUSED_SPACE
(segment_owner IN VARCHAR2
,segment_name IN VARCHAR2
,segment_type IN VARCHAR2
,total_blocks OUT NUMBER
,total_bytes OUT NUMBER
,unused_blocks OUT NUMBER
,unused_bytes OUT NUMBER
,last_used_extent_file_id OUT NUMBER
,last_used_extent_block_id OUT NUMBER
,last_used_block OUT NUMBER
,partition_name IN VARCHAR2 DEFAULT NULL);
Parameters are summarized in the following table
segment_owner Schema of segment
segment_type Type of segment
total_blocks Total data blocks in segment
total_bytes Total bytes in segment
unused_blocks Total unused blocks in segment
unused_bytes Total unused bytes in segment
last_used_extent_file_id File id of last used extent
last_used_extent_block_id Block id of last used extent
last_used_block Last used block in extent
partition_name Name of partition (8.0 only)
Trang 212.1.2.2.1 Exceptions
The UNUSED_SPACE procedure does not raise any package exceptions UNUSED_SPACE will raise the following Oracle exception if invalid segment data is passed in or if the executing user does not have
privileges to use the procedure on the segment:
ORA−00942
Table or view does not exist
12.1.2.2.2 Restrictions
Note the following restrictions on calling the UNUSED_SPACE procedure:
•
The user must have the ANALYZE ANY system privilege to use UNUSED_SPACE on segments from schemas other than the current session schema
•
The program does not assert a purity level with the RESTRICT_REFERENCES pragma
12.1.2.2.3 Example
The following is a simple SQL*Plus report on space utilization by tables in the current session schema It displays total space allocated, total unused space, and the percentage of allocated space that is unused
//* Filename on companion disk: spcex1.sql */*
DECLARE
total_blocks NUMBER;
total_bytes NUMBER;
unused_blocks NUMBER;
unused_bytes NUMBER;
last_extent_file NUMBER;
last_extent_block NUMBER;
last_block NUMBER;
grand_total_blocks NUMBER := 0;
grand_total_unused NUMBER := 0;
BEGIN
FOR user_tables_rec IN
(SELECT table_name
FROM user_tables)
LOOP
DBMS_SPACE.UNUSED_SPACE
(segment_owner => USER
,segment_name => user_tables_rec.table_name
,segment_type => 'TABLE'
,total_blocks => total_blocks
,total_bytes => total_bytes
,unused_blocks => unused_blocks
,unused_bytes => unused_bytes
,last_used_extent_file_id => last_extent_file
,last_used_extent_block_id => last_extent_block
,last_used_block => last_block
);
grand_total_blocks := grand_total_blocks + total_blocks;
grand_total_unused := grand_total_unused + unused_blocks;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Space utilization (TABLES) ');
DBMS_OUTPUT.PUT_LINE('total blocks: '||
Trang 3TO_CHAR(grand_total_blocks) );
DBMS_OUTPUT.PUT_LINE('unused blocks: '||
TO_CHAR(grand_total_unused) );
DBMS_OUTPUT.PUT_LINE('pct unused: '||
TO_CHAR(ROUND((grand_total_unused/grand_total_blocks)*100) ) );
END;
/
This is a sample of the report output:
Space utilization (TABLES)
total blocks: 1237
unused blocks: 613
pct unused: 50
In Oracle 8.0, the partition_name parameter was added to support space analysis for partitioned segments Since the new parameter has a default value, calls to UNUSED_SPACE written to the version 7.x
specification will continue to work under 8.0
WARNING: Under Oracle 8.0, calling DBMS_SPACE.UNUSED_SPACE for a segment
results in a DDL lock being held on the segment until the PL/SQL scope within which the call
is made completes This prevents any other DDL from being executed on the segment, so
long−running programs that use the UNUSED_SPACE procedure could cause unexpected
interference with other DDL operations in the database
Unused space can be deallocated from segments and returned to the free space for the segment's tablespace using the following SQL command:
ALTER [ TABLE | INDEX | CLUSTER ] segment_name DEALLOCATE UNUSED;
For information on how Oracle allocates and manages segment space, see the Oracle7 Server Concepts
manual For information on the DEALLOCATE UNUSED clause of the ALTER TABLE statement, see the
Oracle7 Server SQL Reference.
12.1.3 DBMS_SPACE Examples
The DBMS_SPACE package is a good example of how Oracle Corporation is using the built−in packages to expose, in a controlled way, information about database internals not found in the data dictionary
DBAs managing large transaction−oriented databases must pay attention to space utilization within segments The UNUSED_SPACE procedure provides an additional level of detail that can help the DBAs make better use of space For instance, wasted space that can be freed back to the tablespace for use by other segments can
be detected and measured Also, segment growth rates can be measured more accurately than by monitoring extent allocation, providing better information on the need to expand tablespaces
DBAs, especially those with Oracle parallel server installations, will be interested additionally in monitoring the segment freelist information exposed by the FREE_BLOCKS procedure
Figure 12.1 illustrates how the blocks of a segment fall into one of three categories: used, unused (above the highwater mark), and on the free list The latter two categories are the subject of the UNUSED_SPACE and FREE_BLOCKS procedures, respectively
Figure 12.1: Space utilization in a segment
Trang 4I really like the information available in the DBMS_SPACE programs However, I find that the programs are very unwieldy to use, due to their long, cumbersome parameter lists The UNUSED_SPACE procedure has at least three IN parameters and seven OUT parameters! Even the earlier simple illustrative example is many lines long What if you're interested in only one of the OUT parameters ưư say, unused_blocks? You still have to allocate variables to hold all the other OUT parameters just to make the procedure call Wouldn't it be nice to simply call a function that returns the unused blocks number for a given segment?
12.1.3.1 The segspace package
As usual, the solution to such usability issues lies in creating a package to encapsulate those unwieldy
program calls with an easierưtoưuse layer of programs Here is the specification for my own package called segspace:
//* Filename on companion disk: segspace.sql */*
CREATE OR REPLACE PACKAGE segspace
/*
|| Extends the DBMS_SPACE package by creating function
|| calls to return individual parameter values
||
|| Author: John Beresniewicz, Savant Corp
|| Created: 07/29/97
||
|| Compilation Requirements:
||
|| Execution Requirements:
||
|| ANALYZE ANY system privilege
||
*/
AS
/*
|| sets the specified segment as current context
*/
PROCEDURE set_segment
(name_IN IN VARCHAR2
,type_IN IN VARCHAR2
,schema_IN IN VARCHAR2
,partition_IN IN VARCHAR2 DEFAULT NULL);
/* returns current segment name */
FUNCTION current_name RETURN VARCHAR2;
/* returns current segment type */
Trang 5/* returns current segment schema */
FUNCTION current_schema RETURN VARCHAR2;
/*
|| returns total_blocks from DBMS_SPACE.UNUSED_SPACE
|| for the segment specified
*/
FUNCTION total_blocks
(name_IN IN VARCHAR2 DEFAULT current_name
,type_IN IN VARCHAR2 DEFAULT current_type
,schema_IN IN VARCHAR2 DEFAULT current_schema)
RETURN NUMBER;
/*
|| returns unused_blocks from DBMS_SPACE.UNUSED_SPACE
|| for the segment specified
*/
FUNCTION unused_blocks
(name_IN IN VARCHAR2 DEFAULT current_name
,type_IN IN VARCHAR2 DEFAULT current_type
,schema_IN IN VARCHAR2 DEFAULT current_schema)
RETURN NUMBER;
/*
|| returns number of blocks on segment freelist using
|| DBMS_SPACE.FREE_BLOCKS
*/
FUNCTION freelist_blocks
(name_IN IN VARCHAR2 DEFAULT current_name
,type_IN IN VARCHAR2 DEFAULT current_type
,schema_IN IN VARCHAR2 DEFAULT current_schema
,freelist_group_IN IN NUMBER DEFAULT 0
,partition_IN IN VARCHAR2 DEFAULT NULL)
RETURN NUMBER;
END segspace;
The segspace package has functions called total_blocks and unused_blocks These functions both accept segment identification information as IN parameters and return the value of their corresponding OUT
parameters from DBMS_SPACE.UNUSED_SPACE So in SQL*Plus, you can use these functions as follows:
SQL> var tot_blks NUMBER
SQL> execute :tot_blks := segspace.total_blocks('TENK','TABLE','LOAD1');
PL/SQL procedure successfully completed.
SQL> print tot_blks
TOT_BLKS
−−−−−−−−−
455
Well, this sure is a lot easier than calling the UNUSED_SPACE procedure directly! Notice, however, that the
IN parameters to these functions also all have default values, which means that they can be suppressed when making the function call (as long as the default is the desired value) The default values used are the segment identifiers (name, type, and schema) most recently specified Thus we can find out the unused blocks for the LOAD1.TENK table by immediately following the preceding call with this:
SQL> var unused_blks number
SQL> execute :unused_blks := segspace.unused_blocks;